@clayroach/effect 3.19.14-source-capture.8 → 3.19.14-source-trace.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (452) hide show
  1. package/SourceLocation/package.json +6 -0
  2. package/dist/cjs/Effect.js +2 -28
  3. package/dist/cjs/Effect.js.map +1 -1
  4. package/dist/cjs/FiberRef.js +12 -1
  5. package/dist/cjs/FiberRef.js.map +1 -1
  6. package/dist/cjs/Layer.js +2 -24
  7. package/dist/cjs/Layer.js.map +1 -1
  8. package/dist/cjs/RuntimeFlags.js +1 -29
  9. package/dist/cjs/RuntimeFlags.js.map +1 -1
  10. package/dist/cjs/SourceLocation.js +60 -0
  11. package/dist/cjs/SourceLocation.js.map +1 -0
  12. package/dist/cjs/Tracer.js +1 -15
  13. package/dist/cjs/Tracer.js.map +1 -1
  14. package/dist/cjs/Utils.js +1 -1
  15. package/dist/cjs/Utils.js.map +1 -1
  16. package/dist/cjs/index.js +3 -1
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/internal/clock.js +1 -1
  19. package/dist/cjs/internal/clock.js.map +1 -1
  20. package/dist/cjs/internal/core.js +17 -50
  21. package/dist/cjs/internal/core.js.map +1 -1
  22. package/dist/cjs/internal/effect/circular.js +18 -30
  23. package/dist/cjs/internal/effect/circular.js.map +1 -1
  24. package/dist/cjs/internal/fiberRuntime.js +16 -65
  25. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  26. package/dist/cjs/internal/layer/circular.js +1 -5
  27. package/dist/cjs/internal/layer/circular.js.map +1 -1
  28. package/dist/cjs/internal/layer.js +1 -3
  29. package/dist/cjs/internal/layer.js.map +1 -1
  30. package/dist/cjs/internal/logger.js +25 -2
  31. package/dist/cjs/internal/logger.js.map +1 -1
  32. package/dist/cjs/internal/runtimeFlags.js +2 -11
  33. package/dist/cjs/internal/runtimeFlags.js.map +1 -1
  34. package/dist/cjs/internal/tracer.js +1 -114
  35. package/dist/cjs/internal/tracer.js.map +1 -1
  36. package/dist/dts/Config.d.ts +2 -2
  37. package/dist/dts/Config.d.ts.map +1 -1
  38. package/dist/dts/Effect.d.ts +8 -29
  39. package/dist/dts/Effect.d.ts.map +1 -1
  40. package/dist/dts/FiberRef.d.ts +12 -0
  41. package/dist/dts/FiberRef.d.ts.map +1 -1
  42. package/dist/dts/Layer.d.ts +0 -22
  43. package/dist/dts/Layer.d.ts.map +1 -1
  44. package/dist/dts/RuntimeFlags.d.ts +0 -28
  45. package/dist/dts/RuntimeFlags.d.ts.map +1 -1
  46. package/dist/dts/SourceLocation.d.ts +88 -0
  47. package/dist/dts/SourceLocation.d.ts.map +1 -0
  48. package/dist/dts/Tracer.d.ts +0 -15
  49. package/dist/dts/Tracer.d.ts.map +1 -1
  50. package/dist/dts/index.d.ts +6 -0
  51. package/dist/dts/index.d.ts.map +1 -1
  52. package/dist/dts/internal/core.d.ts.map +1 -1
  53. package/dist/dts/internal/layer.d.ts.map +1 -1
  54. package/dist/dts/internal/runtimeFlags.d.ts.map +1 -1
  55. package/dist/esm/Effect.js +0 -26
  56. package/dist/esm/Effect.js.map +1 -1
  57. package/dist/esm/FiberRef.js +11 -0
  58. package/dist/esm/FiberRef.js.map +1 -1
  59. package/dist/esm/Layer.js +0 -22
  60. package/dist/esm/Layer.js.map +1 -1
  61. package/dist/esm/RuntimeFlags.js +0 -28
  62. package/dist/esm/RuntimeFlags.js.map +1 -1
  63. package/dist/esm/SourceLocation.js +51 -0
  64. package/dist/esm/SourceLocation.js.map +1 -0
  65. package/dist/esm/Tracer.js +0 -14
  66. package/dist/esm/Tracer.js.map +1 -1
  67. package/dist/esm/Utils.js +1 -1
  68. package/dist/esm/Utils.js.map +1 -1
  69. package/dist/esm/index.js +6 -0
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/internal/clock.js +1 -1
  72. package/dist/esm/internal/clock.js.map +1 -1
  73. package/dist/esm/internal/core.js +12 -45
  74. package/dist/esm/internal/core.js.map +1 -1
  75. package/dist/esm/internal/effect/circular.js +18 -30
  76. package/dist/esm/internal/effect/circular.js.map +1 -1
  77. package/dist/esm/internal/fiberRuntime.js +13 -60
  78. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  79. package/dist/esm/internal/layer/circular.js +0 -4
  80. package/dist/esm/internal/layer/circular.js.map +1 -1
  81. package/dist/esm/internal/layer.js +0 -2
  82. package/dist/esm/internal/layer.js.map +1 -1
  83. package/dist/esm/internal/logger.js +25 -2
  84. package/dist/esm/internal/logger.js.map +1 -1
  85. package/dist/esm/internal/runtimeFlags.js +1 -9
  86. package/dist/esm/internal/runtimeFlags.js.map +1 -1
  87. package/dist/esm/internal/tracer.js +0 -111
  88. package/dist/esm/internal/tracer.js.map +1 -1
  89. package/package.json +12 -1
  90. package/src/Arbitrary.ts +1101 -0
  91. package/src/Array.ts +3589 -0
  92. package/src/BigDecimal.ts +1349 -0
  93. package/src/BigInt.ts +643 -0
  94. package/src/Boolean.ts +287 -0
  95. package/src/Brand.ts +360 -0
  96. package/src/Cache.ts +281 -0
  97. package/src/Cause.ts +1555 -0
  98. package/src/Channel.ts +2355 -0
  99. package/src/ChildExecutorDecision.ts +146 -0
  100. package/src/Chunk.ts +1495 -0
  101. package/src/Clock.ts +111 -0
  102. package/src/Config.ts +542 -0
  103. package/src/ConfigError.ts +270 -0
  104. package/src/ConfigProvider.ts +333 -0
  105. package/src/ConfigProviderPathPatch.ts +100 -0
  106. package/src/Console.ts +226 -0
  107. package/src/Context.ts +585 -0
  108. package/src/Cron.ts +706 -0
  109. package/src/Data.ts +596 -0
  110. package/src/DateTime.ts +1686 -0
  111. package/src/DefaultServices.ts +34 -0
  112. package/src/Deferred.ts +301 -0
  113. package/src/Differ.ts +450 -0
  114. package/src/Duration.ts +1000 -0
  115. package/src/Effect.ts +14817 -0
  116. package/src/Effectable.ts +107 -0
  117. package/src/Either.ts +1040 -0
  118. package/src/Encoding.ts +195 -0
  119. package/src/Equal.ts +98 -0
  120. package/src/Equivalence.ts +235 -0
  121. package/src/ExecutionPlan.ts +308 -0
  122. package/src/ExecutionStrategy.ts +119 -0
  123. package/src/Exit.ts +467 -0
  124. package/src/FastCheck.ts +9 -0
  125. package/src/Fiber.ts +744 -0
  126. package/src/FiberHandle.ts +540 -0
  127. package/src/FiberId.ts +195 -0
  128. package/src/FiberMap.ts +656 -0
  129. package/src/FiberRef.ts +444 -0
  130. package/src/FiberRefs.ts +204 -0
  131. package/src/FiberRefsPatch.ts +105 -0
  132. package/src/FiberSet.ts +491 -0
  133. package/src/FiberStatus.ts +108 -0
  134. package/src/Function.ts +1222 -0
  135. package/src/GlobalValue.ts +53 -0
  136. package/src/Graph.ts +3732 -0
  137. package/src/GroupBy.ts +103 -0
  138. package/src/HKT.ts +45 -0
  139. package/src/Hash.ts +195 -0
  140. package/src/HashMap.ts +519 -0
  141. package/src/HashRing.ts +317 -0
  142. package/src/HashSet.ts +2346 -0
  143. package/src/Inspectable.ts +287 -0
  144. package/src/Iterable.ts +1119 -0
  145. package/src/JSONSchema.ts +1044 -0
  146. package/src/KeyedPool.ts +167 -0
  147. package/src/Layer.ts +1228 -0
  148. package/src/LayerMap.ts +436 -0
  149. package/src/List.ts +977 -0
  150. package/src/LogLevel.ts +285 -0
  151. package/src/LogSpan.ts +25 -0
  152. package/src/Logger.ts +702 -0
  153. package/src/Mailbox.ts +268 -0
  154. package/src/ManagedRuntime.ts +180 -0
  155. package/src/Match.ts +1477 -0
  156. package/src/MergeDecision.ts +95 -0
  157. package/src/MergeState.ts +172 -0
  158. package/src/MergeStrategy.ts +107 -0
  159. package/src/Metric.ts +780 -0
  160. package/src/MetricBoundaries.ts +69 -0
  161. package/src/MetricHook.ts +151 -0
  162. package/src/MetricKey.ts +224 -0
  163. package/src/MetricKeyType.ts +262 -0
  164. package/src/MetricLabel.ts +47 -0
  165. package/src/MetricPair.ts +71 -0
  166. package/src/MetricPolling.ts +148 -0
  167. package/src/MetricRegistry.ts +48 -0
  168. package/src/MetricState.ts +257 -0
  169. package/src/Micro.ts +4405 -0
  170. package/src/ModuleVersion.ts +18 -0
  171. package/src/MutableHashMap.ts +411 -0
  172. package/src/MutableHashSet.ts +706 -0
  173. package/src/MutableList.ts +297 -0
  174. package/src/MutableQueue.ts +227 -0
  175. package/src/MutableRef.ts +202 -0
  176. package/src/NonEmptyIterable.ts +32 -0
  177. package/src/Number.ts +1071 -0
  178. package/src/Option.ts +2170 -0
  179. package/src/Order.ts +373 -0
  180. package/src/Ordering.ts +111 -0
  181. package/src/ParseResult.ts +2031 -0
  182. package/src/PartitionedSemaphore.ts +200 -0
  183. package/src/Pipeable.ts +566 -0
  184. package/src/Pool.ts +204 -0
  185. package/src/Predicate.ts +1405 -0
  186. package/src/Pretty.ts +205 -0
  187. package/src/PrimaryKey.ts +23 -0
  188. package/src/PubSub.ts +182 -0
  189. package/src/Queue.ts +644 -0
  190. package/src/Random.ts +204 -0
  191. package/src/RateLimiter.ts +138 -0
  192. package/src/RcMap.ts +141 -0
  193. package/src/RcRef.ts +122 -0
  194. package/src/Readable.ts +93 -0
  195. package/src/Record.ts +1274 -0
  196. package/src/RedBlackTree.ts +421 -0
  197. package/src/Redacted.ts +144 -0
  198. package/src/Ref.ts +180 -0
  199. package/src/RegExp.ts +38 -0
  200. package/src/Reloadable.ts +127 -0
  201. package/src/Request.ts +347 -0
  202. package/src/RequestBlock.ts +118 -0
  203. package/src/RequestResolver.ts +366 -0
  204. package/src/Resource.ts +119 -0
  205. package/src/Runtime.ts +383 -0
  206. package/src/RuntimeFlags.ts +336 -0
  207. package/src/RuntimeFlagsPatch.ts +183 -0
  208. package/src/STM.ts +2045 -0
  209. package/src/Schedule.ts +2219 -0
  210. package/src/ScheduleDecision.ts +62 -0
  211. package/src/ScheduleInterval.ts +151 -0
  212. package/src/ScheduleIntervals.ts +122 -0
  213. package/src/Scheduler.ts +353 -0
  214. package/src/Schema.ts +10914 -0
  215. package/src/SchemaAST.ts +3043 -0
  216. package/src/Scope.ts +204 -0
  217. package/src/ScopedCache.ts +151 -0
  218. package/src/ScopedRef.ts +117 -0
  219. package/src/Secret.ts +88 -0
  220. package/src/SingleProducerAsyncInput.ts +67 -0
  221. package/src/Sink.ts +1461 -0
  222. package/src/SortedMap.ts +287 -0
  223. package/src/SortedSet.ts +390 -0
  224. package/src/SourceLocation.ts +108 -0
  225. package/src/Stream.ts +6468 -0
  226. package/src/StreamEmit.ts +136 -0
  227. package/src/StreamHaltStrategy.ts +123 -0
  228. package/src/Streamable.ts +45 -0
  229. package/src/String.ts +778 -0
  230. package/src/Struct.ts +243 -0
  231. package/src/Subscribable.ts +100 -0
  232. package/src/SubscriptionRef.ts +298 -0
  233. package/src/Supervisor.ts +240 -0
  234. package/src/Symbol.ts +29 -0
  235. package/src/SynchronizedRef.ts +270 -0
  236. package/src/TArray.ts +495 -0
  237. package/src/TDeferred.ts +100 -0
  238. package/src/TMap.ts +515 -0
  239. package/src/TPriorityQueue.ts +223 -0
  240. package/src/TPubSub.ts +200 -0
  241. package/src/TQueue.ts +432 -0
  242. package/src/TRandom.ts +129 -0
  243. package/src/TReentrantLock.ts +224 -0
  244. package/src/TRef.ts +178 -0
  245. package/src/TSemaphore.ts +129 -0
  246. package/src/TSet.ts +365 -0
  247. package/src/TSubscriptionRef.ts +192 -0
  248. package/src/Take.ts +258 -0
  249. package/src/TestAnnotation.ts +158 -0
  250. package/src/TestAnnotationMap.ts +119 -0
  251. package/src/TestAnnotations.ts +117 -0
  252. package/src/TestClock.ts +556 -0
  253. package/src/TestConfig.ts +47 -0
  254. package/src/TestContext.ts +36 -0
  255. package/src/TestLive.ts +53 -0
  256. package/src/TestServices.ts +390 -0
  257. package/src/TestSized.ts +55 -0
  258. package/src/Tracer.ts +182 -0
  259. package/src/Trie.ts +840 -0
  260. package/src/Tuple.ts +305 -0
  261. package/src/Types.ts +353 -0
  262. package/src/Unify.ts +113 -0
  263. package/src/UpstreamPullRequest.ts +117 -0
  264. package/src/UpstreamPullStrategy.ts +121 -0
  265. package/src/Utils.ts +809 -0
  266. package/src/index.ts +1568 -0
  267. package/src/internal/array.ts +8 -0
  268. package/src/internal/blockedRequests.ts +520 -0
  269. package/src/internal/cache.ts +733 -0
  270. package/src/internal/cause.ts +1050 -0
  271. package/src/internal/channel/channelExecutor.ts +1200 -0
  272. package/src/internal/channel/channelState.ts +134 -0
  273. package/src/internal/channel/childExecutorDecision.ts +96 -0
  274. package/src/internal/channel/continuation.ts +200 -0
  275. package/src/internal/channel/mergeDecision.ts +113 -0
  276. package/src/internal/channel/mergeState.ts +120 -0
  277. package/src/internal/channel/mergeStrategy.ts +72 -0
  278. package/src/internal/channel/singleProducerAsyncInput.ts +259 -0
  279. package/src/internal/channel/subexecutor.ts +229 -0
  280. package/src/internal/channel/upstreamPullRequest.ts +84 -0
  281. package/src/internal/channel/upstreamPullStrategy.ts +87 -0
  282. package/src/internal/channel.ts +2603 -0
  283. package/src/internal/clock.ts +95 -0
  284. package/src/internal/completedRequestMap.ts +9 -0
  285. package/src/internal/concurrency.ts +54 -0
  286. package/src/internal/config.ts +716 -0
  287. package/src/internal/configError.ts +304 -0
  288. package/src/internal/configProvider/pathPatch.ts +97 -0
  289. package/src/internal/configProvider.ts +799 -0
  290. package/src/internal/console.ts +153 -0
  291. package/src/internal/context.ts +337 -0
  292. package/src/internal/core-effect.ts +2293 -0
  293. package/src/internal/core-stream.ts +998 -0
  294. package/src/internal/core.ts +3189 -0
  295. package/src/internal/data.ts +36 -0
  296. package/src/internal/dataSource.ts +327 -0
  297. package/src/internal/dateTime.ts +1277 -0
  298. package/src/internal/defaultServices/console.ts +100 -0
  299. package/src/internal/defaultServices.ts +163 -0
  300. package/src/internal/deferred.ts +46 -0
  301. package/src/internal/differ/chunkPatch.ts +211 -0
  302. package/src/internal/differ/contextPatch.ts +232 -0
  303. package/src/internal/differ/hashMapPatch.ts +220 -0
  304. package/src/internal/differ/hashSetPatch.ts +176 -0
  305. package/src/internal/differ/orPatch.ts +311 -0
  306. package/src/internal/differ/readonlyArrayPatch.ts +210 -0
  307. package/src/internal/differ.ts +200 -0
  308. package/src/internal/doNotation.ts +80 -0
  309. package/src/internal/effect/circular.ts +895 -0
  310. package/src/internal/effectable.ts +131 -0
  311. package/src/internal/either.ts +110 -0
  312. package/src/internal/encoding/base64.ts +286 -0
  313. package/src/internal/encoding/base64Url.ts +29 -0
  314. package/src/internal/encoding/common.ts +51 -0
  315. package/src/internal/encoding/hex.ts +315 -0
  316. package/src/internal/errors.ts +7 -0
  317. package/src/internal/executionPlan.ts +114 -0
  318. package/src/internal/executionStrategy.ts +74 -0
  319. package/src/internal/fiber.ts +388 -0
  320. package/src/internal/fiberId.ts +267 -0
  321. package/src/internal/fiberMessage.ts +82 -0
  322. package/src/internal/fiberRefs/patch.ts +144 -0
  323. package/src/internal/fiberRefs.ts +297 -0
  324. package/src/internal/fiberRuntime.ts +3842 -0
  325. package/src/internal/fiberScope.ts +71 -0
  326. package/src/internal/fiberStatus.ts +119 -0
  327. package/src/internal/groupBy.ts +530 -0
  328. package/src/internal/hashMap/array.ts +49 -0
  329. package/src/internal/hashMap/bitwise.ts +32 -0
  330. package/src/internal/hashMap/config.ts +14 -0
  331. package/src/internal/hashMap/keySet.ts +8 -0
  332. package/src/internal/hashMap/node.ts +391 -0
  333. package/src/internal/hashMap.ts +586 -0
  334. package/src/internal/hashSet.ts +323 -0
  335. package/src/internal/keyedPool.ts +244 -0
  336. package/src/internal/layer/circular.ts +214 -0
  337. package/src/internal/layer.ts +1483 -0
  338. package/src/internal/logSpan.ts +20 -0
  339. package/src/internal/logger-circular.ts +24 -0
  340. package/src/internal/logger.ts +522 -0
  341. package/src/internal/mailbox.ts +561 -0
  342. package/src/internal/managedRuntime/circular.ts +6 -0
  343. package/src/internal/managedRuntime.ts +134 -0
  344. package/src/internal/matcher.ts +652 -0
  345. package/src/internal/metric/boundaries.ts +75 -0
  346. package/src/internal/metric/hook.ts +483 -0
  347. package/src/internal/metric/key.ts +167 -0
  348. package/src/internal/metric/keyType.ts +238 -0
  349. package/src/internal/metric/label.ts +41 -0
  350. package/src/internal/metric/pair.ts +48 -0
  351. package/src/internal/metric/polling.ts +149 -0
  352. package/src/internal/metric/registry.ts +187 -0
  353. package/src/internal/metric/state.ts +290 -0
  354. package/src/internal/metric.ts +577 -0
  355. package/src/internal/opCodes/cause.ts +35 -0
  356. package/src/internal/opCodes/channel.ts +83 -0
  357. package/src/internal/opCodes/channelChildExecutorDecision.ts +17 -0
  358. package/src/internal/opCodes/channelMergeDecision.ts +11 -0
  359. package/src/internal/opCodes/channelMergeState.ts +17 -0
  360. package/src/internal/opCodes/channelMergeStrategy.ts +11 -0
  361. package/src/internal/opCodes/channelState.ts +23 -0
  362. package/src/internal/opCodes/channelUpstreamPullRequest.ts +11 -0
  363. package/src/internal/opCodes/channelUpstreamPullStrategy.ts +11 -0
  364. package/src/internal/opCodes/config.ts +65 -0
  365. package/src/internal/opCodes/configError.ts +35 -0
  366. package/src/internal/opCodes/continuation.ts +11 -0
  367. package/src/internal/opCodes/deferred.ts +11 -0
  368. package/src/internal/opCodes/effect.ts +89 -0
  369. package/src/internal/opCodes/layer.ts +59 -0
  370. package/src/internal/opCodes/streamHaltStrategy.ts +23 -0
  371. package/src/internal/option.ts +80 -0
  372. package/src/internal/pool.ts +432 -0
  373. package/src/internal/pubsub.ts +1762 -0
  374. package/src/internal/query.ts +204 -0
  375. package/src/internal/queue.ts +766 -0
  376. package/src/internal/random.ts +161 -0
  377. package/src/internal/rateLimiter.ts +93 -0
  378. package/src/internal/rcMap.ts +285 -0
  379. package/src/internal/rcRef.ts +192 -0
  380. package/src/internal/redBlackTree/iterator.ts +200 -0
  381. package/src/internal/redBlackTree/node.ts +68 -0
  382. package/src/internal/redBlackTree.ts +1245 -0
  383. package/src/internal/redacted.ts +73 -0
  384. package/src/internal/ref.ts +171 -0
  385. package/src/internal/reloadable.ts +140 -0
  386. package/src/internal/request.ts +177 -0
  387. package/src/internal/resource.ts +76 -0
  388. package/src/internal/ringBuffer.ts +68 -0
  389. package/src/internal/runtime.ts +558 -0
  390. package/src/internal/runtimeFlags.ts +178 -0
  391. package/src/internal/runtimeFlagsPatch.ts +103 -0
  392. package/src/internal/schedule/decision.ts +47 -0
  393. package/src/internal/schedule/interval.ts +101 -0
  394. package/src/internal/schedule/intervals.ts +180 -0
  395. package/src/internal/schedule.ts +2199 -0
  396. package/src/internal/schema/errors.ts +191 -0
  397. package/src/internal/schema/schemaId.ts +106 -0
  398. package/src/internal/schema/util.ts +50 -0
  399. package/src/internal/scopedCache.ts +644 -0
  400. package/src/internal/scopedRef.ts +118 -0
  401. package/src/internal/secret.ts +89 -0
  402. package/src/internal/singleShotGen.ts +35 -0
  403. package/src/internal/sink.ts +2120 -0
  404. package/src/internal/stack.ts +10 -0
  405. package/src/internal/stm/core.ts +817 -0
  406. package/src/internal/stm/entry.ts +59 -0
  407. package/src/internal/stm/journal.ts +123 -0
  408. package/src/internal/stm/opCodes/stm.ts +71 -0
  409. package/src/internal/stm/opCodes/stmState.ts +17 -0
  410. package/src/internal/stm/opCodes/strategy.ts +17 -0
  411. package/src/internal/stm/opCodes/tExit.ts +29 -0
  412. package/src/internal/stm/opCodes/tryCommit.ts +11 -0
  413. package/src/internal/stm/stm.ts +1453 -0
  414. package/src/internal/stm/stmState.ts +136 -0
  415. package/src/internal/stm/tArray.ts +550 -0
  416. package/src/internal/stm/tDeferred.ts +81 -0
  417. package/src/internal/stm/tExit.ts +190 -0
  418. package/src/internal/stm/tMap.ts +824 -0
  419. package/src/internal/stm/tPriorityQueue.ts +267 -0
  420. package/src/internal/stm/tPubSub.ts +551 -0
  421. package/src/internal/stm/tQueue.ts +393 -0
  422. package/src/internal/stm/tRandom.ts +140 -0
  423. package/src/internal/stm/tReentrantLock.ts +352 -0
  424. package/src/internal/stm/tRef.ts +195 -0
  425. package/src/internal/stm/tSemaphore.ts +113 -0
  426. package/src/internal/stm/tSet.ts +259 -0
  427. package/src/internal/stm/tSubscriptionRef.ts +286 -0
  428. package/src/internal/stm/tryCommit.ts +34 -0
  429. package/src/internal/stm/txnId.ts +14 -0
  430. package/src/internal/stm/versioned.ts +4 -0
  431. package/src/internal/stream/debounceState.ts +57 -0
  432. package/src/internal/stream/emit.ts +123 -0
  433. package/src/internal/stream/haltStrategy.ts +94 -0
  434. package/src/internal/stream/handoff.ts +187 -0
  435. package/src/internal/stream/handoffSignal.ts +59 -0
  436. package/src/internal/stream/pull.ts +34 -0
  437. package/src/internal/stream/sinkEndReason.ts +30 -0
  438. package/src/internal/stream/zipAllState.ts +88 -0
  439. package/src/internal/stream/zipChunksState.ts +56 -0
  440. package/src/internal/stream.ts +8801 -0
  441. package/src/internal/string-utils.ts +107 -0
  442. package/src/internal/subscriptionRef.ts +138 -0
  443. package/src/internal/supervisor/patch.ts +190 -0
  444. package/src/internal/supervisor.ts +303 -0
  445. package/src/internal/synchronizedRef.ts +114 -0
  446. package/src/internal/take.ts +199 -0
  447. package/src/internal/testing/sleep.ts +27 -0
  448. package/src/internal/testing/suspendedWarningData.ts +85 -0
  449. package/src/internal/testing/warningData.ts +94 -0
  450. package/src/internal/tracer.ts +150 -0
  451. package/src/internal/trie.ts +722 -0
  452. package/src/internal/version.ts +7 -0
@@ -0,0 +1,1349 @@
1
+ /**
2
+ * This module provides utility functions and type class instances for working with the `BigDecimal` type in TypeScript.
3
+ * It includes functions for basic arithmetic operations, as well as type class instances for `Equivalence` and `Order`.
4
+ *
5
+ * A `BigDecimal` allows storing any real number to arbitrary precision; which avoids common floating point errors
6
+ * (such as 0.1 + 0.2 ≠ 0.3) at the cost of complexity.
7
+ *
8
+ * Internally, `BigDecimal` uses a `BigInt` object, paired with a 64-bit integer which determines the position of the
9
+ * decimal point. Therefore, the precision *is not* actually arbitrary, but limited to 2<sup>63</sup> decimal places.
10
+ *
11
+ * It is not recommended to convert a floating point number to a decimal directly, as the floating point representation
12
+ * may be unexpected.
13
+ *
14
+ * @module BigDecimal
15
+ * @since 2.0.0
16
+ * @see {@link module:BigInt} for more similar operations on `bigint` types
17
+ * @see {@link module:Number} for more similar operations on `number` types
18
+ */
19
+
20
+ import * as Equal from "./Equal.js"
21
+ import * as equivalence from "./Equivalence.js"
22
+ import { dual, pipe } from "./Function.js"
23
+ import * as Hash from "./Hash.js"
24
+ import { type Inspectable, NodeInspectSymbol } from "./Inspectable.js"
25
+ import * as Option from "./Option.js"
26
+ import * as order from "./Order.js"
27
+ import type { Ordering } from "./Ordering.js"
28
+ import { type Pipeable, pipeArguments } from "./Pipeable.js"
29
+ import { hasProperty } from "./Predicate.js"
30
+
31
+ const DEFAULT_PRECISION = 100
32
+ const FINITE_INT_REGEX = /^[+-]?\d+$/
33
+
34
+ /**
35
+ * @since 2.0.0
36
+ * @category symbols
37
+ */
38
+ export const TypeId: unique symbol = Symbol.for("effect/BigDecimal")
39
+
40
+ /**
41
+ * @since 2.0.0
42
+ * @category symbol
43
+ */
44
+ export type TypeId = typeof TypeId
45
+
46
+ /**
47
+ * @since 2.0.0
48
+ * @category models
49
+ */
50
+ export interface BigDecimal extends Equal.Equal, Pipeable, Inspectable {
51
+ readonly [TypeId]: TypeId
52
+ readonly value: bigint
53
+ readonly scale: number
54
+ /** @internal */
55
+ normalized?: BigDecimal
56
+ }
57
+
58
+ const BigDecimalProto: Omit<BigDecimal, "value" | "scale" | "normalized"> = {
59
+ [TypeId]: TypeId,
60
+ [Hash.symbol](this: BigDecimal): number {
61
+ const normalized = normalize(this)
62
+ return pipe(
63
+ Hash.hash(normalized.value),
64
+ Hash.combine(Hash.number(normalized.scale)),
65
+ Hash.cached(this)
66
+ )
67
+ },
68
+ [Equal.symbol](this: BigDecimal, that: unknown): boolean {
69
+ return isBigDecimal(that) && equals(this, that)
70
+ },
71
+ toString(this: BigDecimal) {
72
+ return `BigDecimal(${format(this)})`
73
+ },
74
+ toJSON(this: BigDecimal) {
75
+ return {
76
+ _id: "BigDecimal",
77
+ value: String(this.value),
78
+ scale: this.scale
79
+ }
80
+ },
81
+ [NodeInspectSymbol](this: BigDecimal) {
82
+ return this.toJSON()
83
+ },
84
+ pipe() {
85
+ return pipeArguments(this, arguments)
86
+ }
87
+ } as const
88
+
89
+ /**
90
+ * Checks if a given value is a `BigDecimal`.
91
+ *
92
+ * @since 2.0.0
93
+ * @category guards
94
+ */
95
+ export const isBigDecimal = (u: unknown): u is BigDecimal => hasProperty(u, TypeId)
96
+
97
+ /**
98
+ * Creates a `BigDecimal` from a `bigint` value and a scale.
99
+ *
100
+ * @since 2.0.0
101
+ * @category constructors
102
+ */
103
+ export const make = (value: bigint, scale: number): BigDecimal => {
104
+ const o = Object.create(BigDecimalProto)
105
+ o.value = value
106
+ o.scale = scale
107
+ return o
108
+ }
109
+
110
+ /**
111
+ * Internal function used to create pre-normalized `BigDecimal`s.
112
+ *
113
+ * @internal
114
+ */
115
+ export const unsafeMakeNormalized = (value: bigint, scale: number): BigDecimal => {
116
+ if (value !== bigint0 && value % bigint10 === bigint0) {
117
+ throw new RangeError("Value must be normalized")
118
+ }
119
+
120
+ const o = make(value, scale)
121
+ o.normalized = o
122
+ return o
123
+ }
124
+
125
+ const bigint0 = BigInt(0)
126
+ const bigint1 = BigInt(1)
127
+ const bigint10 = BigInt(10)
128
+ const zero = unsafeMakeNormalized(bigint0, 0)
129
+
130
+ /**
131
+ * Normalizes a given `BigDecimal` by removing trailing zeros.
132
+ *
133
+ * **Example**
134
+ *
135
+ * ```ts
136
+ * import * as assert from "node:assert"
137
+ * import { normalize, make, unsafeFromString } from "effect/BigDecimal"
138
+ *
139
+ * assert.deepStrictEqual(normalize(unsafeFromString("123.00000")), normalize(make(123n, 0)))
140
+ * assert.deepStrictEqual(normalize(unsafeFromString("12300000")), normalize(make(123n, -5)))
141
+ * ```
142
+ *
143
+ * @since 2.0.0
144
+ * @category scaling
145
+ */
146
+ export const normalize = (self: BigDecimal): BigDecimal => {
147
+ if (self.normalized === undefined) {
148
+ if (self.value === bigint0) {
149
+ self.normalized = zero
150
+ } else {
151
+ const digits = `${self.value}`
152
+
153
+ let trail = 0
154
+ for (let i = digits.length - 1; i >= 0; i--) {
155
+ if (digits[i] === "0") {
156
+ trail++
157
+ } else {
158
+ break
159
+ }
160
+ }
161
+
162
+ if (trail === 0) {
163
+ self.normalized = self
164
+ }
165
+
166
+ const value = BigInt(digits.substring(0, digits.length - trail))
167
+ const scale = self.scale - trail
168
+ self.normalized = unsafeMakeNormalized(value, scale)
169
+ }
170
+ }
171
+
172
+ return self.normalized
173
+ }
174
+
175
+ /**
176
+ * Scales a given `BigDecimal` to the specified scale.
177
+ *
178
+ * If the given scale is smaller than the current scale, the value will be rounded down to
179
+ * the nearest integer.
180
+ *
181
+ * @since 2.0.0
182
+ * @category scaling
183
+ */
184
+ export const scale: {
185
+ (scale: number): (self: BigDecimal) => BigDecimal
186
+ (self: BigDecimal, scale: number): BigDecimal
187
+ } = dual(2, (self: BigDecimal, scale: number): BigDecimal => {
188
+ if (scale > self.scale) {
189
+ return make(self.value * bigint10 ** BigInt(scale - self.scale), scale)
190
+ }
191
+
192
+ if (scale < self.scale) {
193
+ return make(self.value / bigint10 ** BigInt(self.scale - scale), scale)
194
+ }
195
+
196
+ return self
197
+ })
198
+
199
+ /**
200
+ * Provides an addition operation on `BigDecimal`s.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * import * as assert from "node:assert"
205
+ * import { sum, unsafeFromString } from "effect/BigDecimal"
206
+ *
207
+ * assert.deepStrictEqual(sum(unsafeFromString("2"), unsafeFromString("3")), unsafeFromString("5"))
208
+ * ```
209
+ *
210
+ * @since 2.0.0
211
+ * @category math
212
+ */
213
+ export const sum: {
214
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
215
+ (self: BigDecimal, that: BigDecimal): BigDecimal
216
+ } = dual(2, (self: BigDecimal, that: BigDecimal): BigDecimal => {
217
+ if (that.value === bigint0) {
218
+ return self
219
+ }
220
+
221
+ if (self.value === bigint0) {
222
+ return that
223
+ }
224
+
225
+ if (self.scale > that.scale) {
226
+ return make(scale(that, self.scale).value + self.value, self.scale)
227
+ }
228
+
229
+ if (self.scale < that.scale) {
230
+ return make(scale(self, that.scale).value + that.value, that.scale)
231
+ }
232
+
233
+ return make(self.value + that.value, self.scale)
234
+ })
235
+
236
+ /**
237
+ * Provides a multiplication operation on `BigDecimal`s.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * import * as assert from "node:assert"
242
+ * import { multiply, unsafeFromString } from "effect/BigDecimal"
243
+ *
244
+ * assert.deepStrictEqual(multiply(unsafeFromString("2"), unsafeFromString("3")), unsafeFromString("6"))
245
+ * ```
246
+ *
247
+ * @since 2.0.0
248
+ * @category math
249
+ */
250
+ export const multiply: {
251
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
252
+ (self: BigDecimal, that: BigDecimal): BigDecimal
253
+ } = dual(2, (self: BigDecimal, that: BigDecimal): BigDecimal => {
254
+ if (that.value === bigint0 || self.value === bigint0) {
255
+ return zero
256
+ }
257
+
258
+ return make(self.value * that.value, self.scale + that.scale)
259
+ })
260
+
261
+ /**
262
+ * Provides a subtraction operation on `BigDecimal`s.
263
+ *
264
+ * @example
265
+ * ```ts
266
+ * import * as assert from "node:assert"
267
+ * import { subtract, unsafeFromString } from "effect/BigDecimal"
268
+ *
269
+ * assert.deepStrictEqual(subtract(unsafeFromString("2"), unsafeFromString("3")), unsafeFromString("-1"))
270
+ * ```
271
+ *
272
+ * @since 2.0.0
273
+ * @category math
274
+ */
275
+ export const subtract: {
276
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
277
+ (self: BigDecimal, that: BigDecimal): BigDecimal
278
+ } = dual(2, (self: BigDecimal, that: BigDecimal): BigDecimal => {
279
+ if (that.value === bigint0) {
280
+ return self
281
+ }
282
+
283
+ if (self.value === bigint0) {
284
+ return make(-that.value, that.scale)
285
+ }
286
+
287
+ if (self.scale > that.scale) {
288
+ return make(self.value - scale(that, self.scale).value, self.scale)
289
+ }
290
+
291
+ if (self.scale < that.scale) {
292
+ return make(scale(self, that.scale).value - that.value, that.scale)
293
+ }
294
+
295
+ return make(self.value - that.value, self.scale)
296
+ })
297
+
298
+ /**
299
+ * Internal function used for arbitrary precision division.
300
+ */
301
+ const divideWithPrecision = (
302
+ num: bigint,
303
+ den: bigint,
304
+ scale: number,
305
+ precision: number
306
+ ): BigDecimal => {
307
+ const numNegative = num < bigint0
308
+ const denNegative = den < bigint0
309
+ const negateResult = numNegative !== denNegative
310
+
311
+ num = numNegative ? -num : num
312
+ den = denNegative ? -den : den
313
+
314
+ // Shift digits until numerator is larger than denominator (set scale appropriately).
315
+ while (num < den) {
316
+ num *= bigint10
317
+ scale++
318
+ }
319
+
320
+ // First division.
321
+ let quotient = num / den
322
+ let remainder = num % den
323
+
324
+ if (remainder === bigint0) {
325
+ // No remainder, return immediately.
326
+ return make(negateResult ? -quotient : quotient, scale)
327
+ }
328
+
329
+ // The quotient is guaranteed to be non-negative at this point. No need to consider sign.
330
+ let count = `${quotient}`.length
331
+
332
+ // Shift the remainder by 1 decimal; The quotient will be 1 digit upon next division.
333
+ remainder *= bigint10
334
+ while (remainder !== bigint0 && count < precision) {
335
+ const q = remainder / den
336
+ const r = remainder % den
337
+ quotient = quotient * bigint10 + q
338
+ remainder = r * bigint10
339
+
340
+ count++
341
+ scale++
342
+ }
343
+
344
+ if (remainder !== bigint0) {
345
+ // Round final number with remainder.
346
+ quotient += roundTerminal(remainder / den)
347
+ }
348
+
349
+ return make(negateResult ? -quotient : quotient, scale)
350
+ }
351
+
352
+ /**
353
+ * Internal function used for rounding.
354
+ *
355
+ * Returns 1 if the most significant digit is >= 5, otherwise 0.
356
+ *
357
+ * This is used after dividing a number by a power of ten and rounding the last digit.
358
+ *
359
+ * @internal
360
+ */
361
+ export const roundTerminal = (n: bigint): bigint => {
362
+ const pos = n >= bigint0 ? 0 : 1
363
+ return Number(`${n}`[pos]) < 5 ? bigint0 : bigint1
364
+ }
365
+
366
+ /**
367
+ * Provides a division operation on `BigDecimal`s.
368
+ *
369
+ * If the dividend is not a multiple of the divisor the result will be a `BigDecimal` value
370
+ * which represents the integer division rounded down to the nearest integer.
371
+ *
372
+ * If the divisor is `0`, the result will be `None`.
373
+ *
374
+ * @example
375
+ * ```ts
376
+ * import * as assert from "node:assert"
377
+ * import { BigDecimal, Option } from "effect"
378
+ *
379
+ * assert.deepStrictEqual(BigDecimal.divide(BigDecimal.unsafeFromString("6"), BigDecimal.unsafeFromString("3")), Option.some(BigDecimal.unsafeFromString("2")))
380
+ * assert.deepStrictEqual(BigDecimal.divide(BigDecimal.unsafeFromString("6"), BigDecimal.unsafeFromString("4")), Option.some(BigDecimal.unsafeFromString("1.5")))
381
+ * assert.deepStrictEqual(BigDecimal.divide(BigDecimal.unsafeFromString("6"), BigDecimal.unsafeFromString("0")), Option.none())
382
+ * ```
383
+ *
384
+ * @since 2.0.0
385
+ * @category math
386
+ */
387
+ export const divide: {
388
+ (that: BigDecimal): (self: BigDecimal) => Option.Option<BigDecimal>
389
+ (self: BigDecimal, that: BigDecimal): Option.Option<BigDecimal>
390
+ } = dual(2, (self: BigDecimal, that: BigDecimal): Option.Option<BigDecimal> => {
391
+ if (that.value === bigint0) {
392
+ return Option.none()
393
+ }
394
+
395
+ if (self.value === bigint0) {
396
+ return Option.some(zero)
397
+ }
398
+
399
+ const scale = self.scale - that.scale
400
+ if (self.value === that.value) {
401
+ return Option.some(make(bigint1, scale))
402
+ }
403
+
404
+ return Option.some(divideWithPrecision(self.value, that.value, scale, DEFAULT_PRECISION))
405
+ })
406
+
407
+ /**
408
+ * Provides an unsafe division operation on `BigDecimal`s.
409
+ *
410
+ * If the dividend is not a multiple of the divisor the result will be a `BigDecimal` value
411
+ * which represents the integer division rounded down to the nearest integer.
412
+ *
413
+ * Throws a `RangeError` if the divisor is `0`.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * import * as assert from "node:assert"
418
+ * import { unsafeDivide, unsafeFromString } from "effect/BigDecimal"
419
+ *
420
+ * assert.deepStrictEqual(unsafeDivide(unsafeFromString("6"), unsafeFromString("3")), unsafeFromString("2"))
421
+ * assert.deepStrictEqual(unsafeDivide(unsafeFromString("6"), unsafeFromString("4")), unsafeFromString("1.5"))
422
+ * ```
423
+ *
424
+ * @since 2.0.0
425
+ * @category math
426
+ */
427
+ export const unsafeDivide: {
428
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
429
+ (self: BigDecimal, that: BigDecimal): BigDecimal
430
+ } = dual(2, (self: BigDecimal, that: BigDecimal): BigDecimal => {
431
+ if (that.value === bigint0) {
432
+ throw new RangeError("Division by zero")
433
+ }
434
+
435
+ if (self.value === bigint0) {
436
+ return zero
437
+ }
438
+
439
+ const scale = self.scale - that.scale
440
+ if (self.value === that.value) {
441
+ return make(bigint1, scale)
442
+ }
443
+ return divideWithPrecision(self.value, that.value, scale, DEFAULT_PRECISION)
444
+ })
445
+
446
+ /**
447
+ * @since 2.0.0
448
+ * @category instances
449
+ */
450
+ export const Order: order.Order<BigDecimal> = order.make((self, that) => {
451
+ const scmp = order.number(sign(self), sign(that))
452
+ if (scmp !== 0) {
453
+ return scmp
454
+ }
455
+
456
+ if (self.scale > that.scale) {
457
+ return order.bigint(self.value, scale(that, self.scale).value)
458
+ }
459
+
460
+ if (self.scale < that.scale) {
461
+ return order.bigint(scale(self, that.scale).value, that.value)
462
+ }
463
+
464
+ return order.bigint(self.value, that.value)
465
+ })
466
+
467
+ /**
468
+ * Returns `true` if the first argument is less than the second, otherwise `false`.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * import * as assert from "node:assert"
473
+ * import { lessThan, unsafeFromString } from "effect/BigDecimal"
474
+ *
475
+ * assert.deepStrictEqual(lessThan(unsafeFromString("2"), unsafeFromString("3")), true)
476
+ * assert.deepStrictEqual(lessThan(unsafeFromString("3"), unsafeFromString("3")), false)
477
+ * assert.deepStrictEqual(lessThan(unsafeFromString("4"), unsafeFromString("3")), false)
478
+ * ```
479
+ *
480
+ * @since 2.0.0
481
+ * @category predicates
482
+ */
483
+ export const lessThan: {
484
+ (that: BigDecimal): (self: BigDecimal) => boolean
485
+ (self: BigDecimal, that: BigDecimal): boolean
486
+ } = order.lessThan(Order)
487
+
488
+ /**
489
+ * Checks if a given `BigDecimal` is less than or equal to the provided one.
490
+ *
491
+ * @example
492
+ * ```ts
493
+ * import * as assert from "node:assert"
494
+ * import { lessThanOrEqualTo, unsafeFromString } from "effect/BigDecimal"
495
+ *
496
+ * assert.deepStrictEqual(lessThanOrEqualTo(unsafeFromString("2"), unsafeFromString("3")), true)
497
+ * assert.deepStrictEqual(lessThanOrEqualTo(unsafeFromString("3"), unsafeFromString("3")), true)
498
+ * assert.deepStrictEqual(lessThanOrEqualTo(unsafeFromString("4"), unsafeFromString("3")), false)
499
+ * ```
500
+ *
501
+ * @since 2.0.0
502
+ * @category predicates
503
+ */
504
+ export const lessThanOrEqualTo: {
505
+ (that: BigDecimal): (self: BigDecimal) => boolean
506
+ (self: BigDecimal, that: BigDecimal): boolean
507
+ } = order.lessThanOrEqualTo(Order)
508
+
509
+ /**
510
+ * Returns `true` if the first argument is greater than the second, otherwise `false`.
511
+ *
512
+ * @example
513
+ * ```ts
514
+ * import * as assert from "node:assert"
515
+ * import { greaterThan, unsafeFromString } from "effect/BigDecimal"
516
+ *
517
+ * assert.deepStrictEqual(greaterThan(unsafeFromString("2"), unsafeFromString("3")), false)
518
+ * assert.deepStrictEqual(greaterThan(unsafeFromString("3"), unsafeFromString("3")), false)
519
+ * assert.deepStrictEqual(greaterThan(unsafeFromString("4"), unsafeFromString("3")), true)
520
+ * ```
521
+ *
522
+ * @since 2.0.0
523
+ * @category predicates
524
+ */
525
+ export const greaterThan: {
526
+ (that: BigDecimal): (self: BigDecimal) => boolean
527
+ (self: BigDecimal, that: BigDecimal): boolean
528
+ } = order.greaterThan(Order)
529
+
530
+ /**
531
+ * Checks if a given `BigDecimal` is greater than or equal to the provided one.
532
+ *
533
+ * @example
534
+ * ```ts
535
+ * import * as assert from "node:assert"
536
+ * import { greaterThanOrEqualTo, unsafeFromString } from "effect/BigDecimal"
537
+ *
538
+ * assert.deepStrictEqual(greaterThanOrEqualTo(unsafeFromString("2"), unsafeFromString("3")), false)
539
+ * assert.deepStrictEqual(greaterThanOrEqualTo(unsafeFromString("3"), unsafeFromString("3")), true)
540
+ * assert.deepStrictEqual(greaterThanOrEqualTo(unsafeFromString("4"), unsafeFromString("3")), true)
541
+ * ```
542
+ *
543
+ * @since 2.0.0
544
+ * @category predicates
545
+ */
546
+ export const greaterThanOrEqualTo: {
547
+ (that: BigDecimal): (self: BigDecimal) => boolean
548
+ (self: BigDecimal, that: BigDecimal): boolean
549
+ } = order.greaterThanOrEqualTo(Order)
550
+
551
+ /**
552
+ * Checks if a `BigDecimal` is between a `minimum` and `maximum` value (inclusive).
553
+ *
554
+ * @example
555
+ * ```ts
556
+ * import * as assert from "node:assert"
557
+ * import { BigDecimal } from "effect"
558
+ *
559
+ * const between = BigDecimal.between({
560
+ * minimum: BigDecimal.unsafeFromString("1"),
561
+ * maximum: BigDecimal.unsafeFromString("5") }
562
+ * )
563
+ *
564
+ * assert.deepStrictEqual(between(BigDecimal.unsafeFromString("3")), true)
565
+ * assert.deepStrictEqual(between(BigDecimal.unsafeFromString("0")), false)
566
+ * assert.deepStrictEqual(between(BigDecimal.unsafeFromString("6")), false)
567
+ * ```
568
+ *
569
+ * @since 2.0.0
570
+ * @category predicates
571
+ */
572
+ export const between: {
573
+ (options: {
574
+ minimum: BigDecimal
575
+ maximum: BigDecimal
576
+ }): (self: BigDecimal) => boolean
577
+ (self: BigDecimal, options: {
578
+ minimum: BigDecimal
579
+ maximum: BigDecimal
580
+ }): boolean
581
+ } = order.between(Order)
582
+
583
+ /**
584
+ * Restricts the given `BigDecimal` to be within the range specified by the `minimum` and `maximum` values.
585
+ *
586
+ * - If the `BigDecimal` is less than the `minimum` value, the function returns the `minimum` value.
587
+ * - If the `BigDecimal` is greater than the `maximum` value, the function returns the `maximum` value.
588
+ * - Otherwise, it returns the original `BigDecimal`.
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * import * as assert from "node:assert"
593
+ * import { BigDecimal } from "effect"
594
+ *
595
+ * const clamp = BigDecimal.clamp({
596
+ * minimum: BigDecimal.unsafeFromString("1"),
597
+ * maximum: BigDecimal.unsafeFromString("5") }
598
+ * )
599
+ *
600
+ * assert.deepStrictEqual(clamp(BigDecimal.unsafeFromString("3")), BigDecimal.unsafeFromString("3"))
601
+ * assert.deepStrictEqual(clamp(BigDecimal.unsafeFromString("0")), BigDecimal.unsafeFromString("1"))
602
+ * assert.deepStrictEqual(clamp(BigDecimal.unsafeFromString("6")), BigDecimal.unsafeFromString("5"))
603
+ * ```
604
+ *
605
+ * @since 2.0.0
606
+ * @category math
607
+ */
608
+ export const clamp: {
609
+ (options: {
610
+ minimum: BigDecimal
611
+ maximum: BigDecimal
612
+ }): (self: BigDecimal) => BigDecimal
613
+ (self: BigDecimal, options: {
614
+ minimum: BigDecimal
615
+ maximum: BigDecimal
616
+ }): BigDecimal
617
+ } = order.clamp(Order)
618
+
619
+ /**
620
+ * Returns the minimum between two `BigDecimal`s.
621
+ *
622
+ * @example
623
+ * ```ts
624
+ * import * as assert from "node:assert"
625
+ * import { min, unsafeFromString } from "effect/BigDecimal"
626
+ *
627
+ * assert.deepStrictEqual(min(unsafeFromString("2"), unsafeFromString("3")), unsafeFromString("2"))
628
+ * ```
629
+ *
630
+ * @since 2.0.0
631
+ * @category math
632
+ */
633
+ export const min: {
634
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
635
+ (self: BigDecimal, that: BigDecimal): BigDecimal
636
+ } = order.min(Order)
637
+
638
+ /**
639
+ * Returns the maximum between two `BigDecimal`s.
640
+ *
641
+ * @example
642
+ * ```ts
643
+ * import * as assert from "node:assert"
644
+ * import { max, unsafeFromString } from "effect/BigDecimal"
645
+ *
646
+ * assert.deepStrictEqual(max(unsafeFromString("2"), unsafeFromString("3")), unsafeFromString("3"))
647
+ * ```
648
+ *
649
+ * @since 2.0.0
650
+ * @category math
651
+ */
652
+ export const max: {
653
+ (that: BigDecimal): (self: BigDecimal) => BigDecimal
654
+ (self: BigDecimal, that: BigDecimal): BigDecimal
655
+ } = order.max(Order)
656
+
657
+ /**
658
+ * Determines the sign of a given `BigDecimal`.
659
+ *
660
+ * @example
661
+ * ```ts
662
+ * import * as assert from "node:assert"
663
+ * import { sign, unsafeFromString } from "effect/BigDecimal"
664
+ *
665
+ * assert.deepStrictEqual(sign(unsafeFromString("-5")), -1)
666
+ * assert.deepStrictEqual(sign(unsafeFromString("0")), 0)
667
+ * assert.deepStrictEqual(sign(unsafeFromString("5")), 1)
668
+ * ```
669
+ *
670
+ * @since 2.0.0
671
+ * @category math
672
+ */
673
+ export const sign = (n: BigDecimal): Ordering => n.value === bigint0 ? 0 : n.value < bigint0 ? -1 : 1
674
+
675
+ /**
676
+ * Determines the absolute value of a given `BigDecimal`.
677
+ *
678
+ * @example
679
+ * ```ts
680
+ * import * as assert from "node:assert"
681
+ * import { abs, unsafeFromString } from "effect/BigDecimal"
682
+ *
683
+ * assert.deepStrictEqual(abs(unsafeFromString("-5")), unsafeFromString("5"))
684
+ * assert.deepStrictEqual(abs(unsafeFromString("0")), unsafeFromString("0"))
685
+ * assert.deepStrictEqual(abs(unsafeFromString("5")), unsafeFromString("5"))
686
+ * ```
687
+ *
688
+ * @since 2.0.0
689
+ * @category math
690
+ */
691
+ export const abs = (n: BigDecimal): BigDecimal => n.value < bigint0 ? make(-n.value, n.scale) : n
692
+
693
+ /**
694
+ * Provides a negate operation on `BigDecimal`s.
695
+ *
696
+ * @example
697
+ * ```ts
698
+ * import * as assert from "node:assert"
699
+ * import { negate, unsafeFromString } from "effect/BigDecimal"
700
+ *
701
+ * assert.deepStrictEqual(negate(unsafeFromString("3")), unsafeFromString("-3"))
702
+ * assert.deepStrictEqual(negate(unsafeFromString("-6")), unsafeFromString("6"))
703
+ * ```
704
+ *
705
+ * @since 2.0.0
706
+ * @category math
707
+ */
708
+ export const negate = (n: BigDecimal): BigDecimal => make(-n.value, n.scale)
709
+
710
+ /**
711
+ * Returns the remainder left over when one operand is divided by a second operand.
712
+ *
713
+ * If the divisor is `0`, the result will be `None`.
714
+ *
715
+ * @example
716
+ * ```ts
717
+ * import * as assert from "node:assert"
718
+ * import { BigDecimal, Option } from "effect"
719
+ *
720
+ * assert.deepStrictEqual(BigDecimal.remainder(BigDecimal.unsafeFromString("2"), BigDecimal.unsafeFromString("2")), Option.some(BigDecimal.unsafeFromString("0")))
721
+ * assert.deepStrictEqual(BigDecimal.remainder(BigDecimal.unsafeFromString("3"), BigDecimal.unsafeFromString("2")), Option.some(BigDecimal.unsafeFromString("1")))
722
+ * assert.deepStrictEqual(BigDecimal.remainder(BigDecimal.unsafeFromString("-4"), BigDecimal.unsafeFromString("2")), Option.some(BigDecimal.unsafeFromString("0")))
723
+ * ```
724
+ *
725
+ * @since 2.0.0
726
+ * @category math
727
+ */
728
+ export const remainder: {
729
+ (divisor: BigDecimal): (self: BigDecimal) => Option.Option<BigDecimal>
730
+ (self: BigDecimal, divisor: BigDecimal): Option.Option<BigDecimal>
731
+ } = dual(2, (self: BigDecimal, divisor: BigDecimal): Option.Option<BigDecimal> => {
732
+ if (divisor.value === bigint0) {
733
+ return Option.none()
734
+ }
735
+
736
+ const max = Math.max(self.scale, divisor.scale)
737
+ return Option.some(make(scale(self, max).value % scale(divisor, max).value, max))
738
+ })
739
+
740
+ /**
741
+ * Returns the remainder left over when one operand is divided by a second operand.
742
+ *
743
+ * Throws a `RangeError` if the divisor is `0`.
744
+ *
745
+ * @example
746
+ * ```ts
747
+ * import * as assert from "node:assert"
748
+ * import { unsafeRemainder, unsafeFromString } from "effect/BigDecimal"
749
+ *
750
+ * assert.deepStrictEqual(unsafeRemainder(unsafeFromString("2"), unsafeFromString("2")), unsafeFromString("0"))
751
+ * assert.deepStrictEqual(unsafeRemainder(unsafeFromString("3"), unsafeFromString("2")), unsafeFromString("1"))
752
+ * assert.deepStrictEqual(unsafeRemainder(unsafeFromString("-4"), unsafeFromString("2")), unsafeFromString("0"))
753
+ * ```
754
+ *
755
+ * @since 2.0.0
756
+ * @category math
757
+ */
758
+ export const unsafeRemainder: {
759
+ (divisor: BigDecimal): (self: BigDecimal) => BigDecimal
760
+ (self: BigDecimal, divisor: BigDecimal): BigDecimal
761
+ } = dual(2, (self: BigDecimal, divisor: BigDecimal): BigDecimal => {
762
+ if (divisor.value === bigint0) {
763
+ throw new RangeError("Division by zero")
764
+ }
765
+
766
+ const max = Math.max(self.scale, divisor.scale)
767
+ return make(scale(self, max).value % scale(divisor, max).value, max)
768
+ })
769
+
770
+ /**
771
+ * @category instances
772
+ * @since 2.0.0
773
+ */
774
+ export const Equivalence: equivalence.Equivalence<BigDecimal> = equivalence.make((self, that) => {
775
+ if (self.scale > that.scale) {
776
+ return scale(that, self.scale).value === self.value
777
+ }
778
+
779
+ if (self.scale < that.scale) {
780
+ return scale(self, that.scale).value === that.value
781
+ }
782
+
783
+ return self.value === that.value
784
+ })
785
+
786
+ /**
787
+ * Checks if two `BigDecimal`s are equal.
788
+ *
789
+ * @since 2.0.0
790
+ * @category predicates
791
+ */
792
+ export const equals: {
793
+ (that: BigDecimal): (self: BigDecimal) => boolean
794
+ (self: BigDecimal, that: BigDecimal): boolean
795
+ } = dual(2, (self: BigDecimal, that: BigDecimal): boolean => Equivalence(self, that))
796
+
797
+ /**
798
+ * Creates a `BigDecimal` from a `bigint` value.
799
+ *
800
+ * @since 2.0.0
801
+ * @category constructors
802
+ */
803
+ export const fromBigInt = (n: bigint): BigDecimal => make(n, 0)
804
+
805
+ /**
806
+ * Creates a `BigDecimal` from a `number` value.
807
+ *
808
+ * It is not recommended to convert a floating point number to a decimal directly,
809
+ * as the floating point representation may be unexpected.
810
+ *
811
+ * Throws a `RangeError` if the number is not finite (`NaN`, `+Infinity` or `-Infinity`).
812
+ *
813
+ * @example
814
+ * ```ts
815
+ * import * as assert from "node:assert"
816
+ * import { unsafeFromNumber, make } from "effect/BigDecimal"
817
+ *
818
+ * assert.deepStrictEqual(unsafeFromNumber(123), make(123n, 0))
819
+ * assert.deepStrictEqual(unsafeFromNumber(123.456), make(123456n, 3))
820
+ * ```
821
+ *
822
+ * @since 3.11.0
823
+ * @category constructors
824
+ */
825
+ export const unsafeFromNumber = (n: number): BigDecimal =>
826
+ Option.getOrThrowWith(safeFromNumber(n), () => new RangeError(`Number must be finite, got ${n}`))
827
+
828
+ /**
829
+ * Creates a `BigDecimal` from a `number` value.
830
+ *
831
+ * It is not recommended to convert a floating point number to a decimal directly,
832
+ * as the floating point representation may be unexpected.
833
+ *
834
+ * Throws a `RangeError` if the number is not finite (`NaN`, `+Infinity` or `-Infinity`).
835
+ *
836
+ * @since 2.0.0
837
+ * @category constructors
838
+ * @deprecated Use {@link unsafeFromNumber} instead.
839
+ */
840
+ export const fromNumber: (n: number) => BigDecimal = unsafeFromNumber
841
+
842
+ // TODO(4.0): Rename this to `fromNumber` after removing the current, unsafe implementation of `fromNumber`.
843
+ /**
844
+ * Creates a `BigDecimal` from a `number` value.
845
+ *
846
+ * It is not recommended to convert a floating point number to a decimal directly,
847
+ * as the floating point representation may be unexpected.
848
+ *
849
+ * Returns `None` if the number is not finite (`NaN`, `+Infinity` or `-Infinity`).
850
+ *
851
+ * @example
852
+ * ```ts
853
+ * import * as assert from "node:assert"
854
+ * import { BigDecimal, Option } from "effect"
855
+ *
856
+ * assert.deepStrictEqual(BigDecimal.safeFromNumber(123), Option.some(BigDecimal.make(123n, 0)))
857
+ * assert.deepStrictEqual(BigDecimal.safeFromNumber(123.456), Option.some(BigDecimal.make(123456n, 3)))
858
+ * assert.deepStrictEqual(BigDecimal.safeFromNumber(Infinity), Option.none())
859
+ * ```
860
+ *
861
+ * @since 3.11.0
862
+ * @category constructors
863
+ */
864
+ export const safeFromNumber = (n: number): Option.Option<BigDecimal> => {
865
+ if (!Number.isFinite(n)) {
866
+ return Option.none()
867
+ }
868
+
869
+ const string = `${n}`
870
+ if (string.includes("e")) {
871
+ return fromString(string)
872
+ }
873
+
874
+ const [lead, trail = ""] = string.split(".")
875
+ return Option.some(make(BigInt(`${lead}${trail}`), trail.length))
876
+ }
877
+
878
+ /**
879
+ * Parses a numerical `string` into a `BigDecimal`.
880
+ *
881
+ * @example
882
+ * ```ts
883
+ * import * as assert from "node:assert"
884
+ * import { BigDecimal, Option } from "effect"
885
+ *
886
+ * assert.deepStrictEqual(BigDecimal.fromString("123"), Option.some(BigDecimal.make(123n, 0)))
887
+ * assert.deepStrictEqual(BigDecimal.fromString("123.456"), Option.some(BigDecimal.make(123456n, 3)))
888
+ * assert.deepStrictEqual(BigDecimal.fromString("123.abc"), Option.none())
889
+ * ```
890
+ *
891
+ * @since 2.0.0
892
+ * @category constructors
893
+ */
894
+ export const fromString = (s: string): Option.Option<BigDecimal> => {
895
+ if (s === "") {
896
+ return Option.some(zero)
897
+ }
898
+
899
+ let base: string
900
+ let exp: number
901
+ const seperator = s.search(/[eE]/)
902
+ if (seperator !== -1) {
903
+ const trail = s.slice(seperator + 1)
904
+ base = s.slice(0, seperator)
905
+ exp = Number(trail)
906
+ if (base === "" || !Number.isSafeInteger(exp) || !FINITE_INT_REGEX.test(trail)) {
907
+ return Option.none()
908
+ }
909
+ } else {
910
+ base = s
911
+ exp = 0
912
+ }
913
+
914
+ let digits: string
915
+ let offset: number
916
+ const dot = base.search(/\./)
917
+ if (dot !== -1) {
918
+ const lead = base.slice(0, dot)
919
+ const trail = base.slice(dot + 1)
920
+ digits = `${lead}${trail}`
921
+ offset = trail.length
922
+ } else {
923
+ digits = base
924
+ offset = 0
925
+ }
926
+
927
+ if (!FINITE_INT_REGEX.test(digits)) {
928
+ return Option.none()
929
+ }
930
+
931
+ const scale = offset - exp
932
+ if (!Number.isSafeInteger(scale)) {
933
+ return Option.none()
934
+ }
935
+
936
+ return Option.some(make(BigInt(digits), scale))
937
+ }
938
+
939
+ /**
940
+ * Parses a numerical `string` into a `BigDecimal`.
941
+ *
942
+ * @example
943
+ * ```ts
944
+ * import * as assert from "node:assert"
945
+ * import { unsafeFromString, make } from "effect/BigDecimal"
946
+ *
947
+ * assert.deepStrictEqual(unsafeFromString("123"), make(123n, 0))
948
+ * assert.deepStrictEqual(unsafeFromString("123.456"), make(123456n, 3))
949
+ * assert.throws(() => unsafeFromString("123.abc"))
950
+ * ```
951
+ *
952
+ * @since 2.0.0
953
+ * @category constructors
954
+ */
955
+ export const unsafeFromString = (s: string): BigDecimal =>
956
+ Option.getOrThrowWith(fromString(s), () => new Error("Invalid numerical string"))
957
+
958
+ /**
959
+ * Formats a given `BigDecimal` as a `string`.
960
+ *
961
+ * If the scale of the `BigDecimal` is greater than or equal to 16, the `BigDecimal` will
962
+ * be formatted in scientific notation.
963
+ *
964
+ * @example
965
+ * ```ts
966
+ * import * as assert from "node:assert"
967
+ * import { format, unsafeFromString } from "effect/BigDecimal"
968
+ *
969
+ * assert.deepStrictEqual(format(unsafeFromString("-5")), "-5")
970
+ * assert.deepStrictEqual(format(unsafeFromString("123.456")), "123.456")
971
+ * assert.deepStrictEqual(format(unsafeFromString("-0.00000123")), "-0.00000123")
972
+ * ```
973
+ *
974
+ * @since 2.0.0
975
+ * @category conversions
976
+ */
977
+ export const format = (n: BigDecimal): string => {
978
+ const normalized = normalize(n)
979
+ if (Math.abs(normalized.scale) >= 16) {
980
+ return toExponential(normalized)
981
+ }
982
+
983
+ const negative = normalized.value < bigint0
984
+ const absolute = negative ? `${normalized.value}`.substring(1) : `${normalized.value}`
985
+
986
+ let before: string
987
+ let after: string
988
+
989
+ if (normalized.scale >= absolute.length) {
990
+ before = "0"
991
+ after = "0".repeat(normalized.scale - absolute.length) + absolute
992
+ } else {
993
+ const location = absolute.length - normalized.scale
994
+ if (location > absolute.length) {
995
+ const zeros = location - absolute.length
996
+ before = `${absolute}${"0".repeat(zeros)}`
997
+ after = ""
998
+ } else {
999
+ after = absolute.slice(location)
1000
+ before = absolute.slice(0, location)
1001
+ }
1002
+ }
1003
+
1004
+ const complete = after === "" ? before : `${before}.${after}`
1005
+ return negative ? `-${complete}` : complete
1006
+ }
1007
+
1008
+ /**
1009
+ * Formats a given `BigDecimal` as a `string` in scientific notation.
1010
+ *
1011
+ * @example
1012
+ * ```ts
1013
+ * import * as assert from "node:assert"
1014
+ * import { toExponential, make } from "effect/BigDecimal"
1015
+ *
1016
+ * assert.deepStrictEqual(toExponential(make(123456n, -5)), "1.23456e+10")
1017
+ * ```
1018
+ *
1019
+ * @since 3.11.0
1020
+ * @category conversions
1021
+ */
1022
+ export const toExponential = (n: BigDecimal): string => {
1023
+ if (isZero(n)) {
1024
+ return "0e+0"
1025
+ }
1026
+
1027
+ const normalized = normalize(n)
1028
+ const digits = `${abs(normalized).value}`
1029
+ const head = digits.slice(0, 1)
1030
+ const tail = digits.slice(1)
1031
+
1032
+ let output = `${isNegative(normalized) ? "-" : ""}${head}`
1033
+ if (tail !== "") {
1034
+ output += `.${tail}`
1035
+ }
1036
+
1037
+ const exp = tail.length - normalized.scale
1038
+ return `${output}e${exp >= 0 ? "+" : ""}${exp}`
1039
+ }
1040
+
1041
+ /**
1042
+ * Converts a `BigDecimal` to a `number`.
1043
+ *
1044
+ * This function will produce incorrect results if the `BigDecimal` exceeds the 64-bit range of a `number`.
1045
+ *
1046
+ * @example
1047
+ * ```ts
1048
+ * import * as assert from "node:assert"
1049
+ * import { unsafeToNumber, unsafeFromString } from "effect/BigDecimal"
1050
+ *
1051
+ * assert.deepStrictEqual(unsafeToNumber(unsafeFromString("123.456")), 123.456)
1052
+ * ```
1053
+ *
1054
+ * @since 2.0.0
1055
+ * @category conversions
1056
+ */
1057
+ export const unsafeToNumber = (n: BigDecimal): number => Number(format(n))
1058
+
1059
+ /**
1060
+ * Checks if a given `BigDecimal` is an integer.
1061
+ *
1062
+ * @example
1063
+ * ```ts
1064
+ * import * as assert from "node:assert"
1065
+ * import { isInteger, unsafeFromString } from "effect/BigDecimal"
1066
+ *
1067
+ * assert.deepStrictEqual(isInteger(unsafeFromString("0")), true)
1068
+ * assert.deepStrictEqual(isInteger(unsafeFromString("1")), true)
1069
+ * assert.deepStrictEqual(isInteger(unsafeFromString("1.1")), false)
1070
+ * ```
1071
+ *
1072
+ * @since 2.0.0
1073
+ * @category predicates
1074
+ */
1075
+ export const isInteger = (n: BigDecimal): boolean => normalize(n).scale <= 0
1076
+
1077
+ /**
1078
+ * Checks if a given `BigDecimal` is `0`.
1079
+ *
1080
+ * @example
1081
+ * ```ts
1082
+ * import * as assert from "node:assert"
1083
+ * import { isZero, unsafeFromString } from "effect/BigDecimal"
1084
+ *
1085
+ * assert.deepStrictEqual(isZero(unsafeFromString("0")), true)
1086
+ * assert.deepStrictEqual(isZero(unsafeFromString("1")), false)
1087
+ * ```
1088
+ *
1089
+ * @since 2.0.0
1090
+ * @category predicates
1091
+ */
1092
+ export const isZero = (n: BigDecimal): boolean => n.value === bigint0
1093
+
1094
+ /**
1095
+ * Checks if a given `BigDecimal` is negative.
1096
+ *
1097
+ * @example
1098
+ * ```ts
1099
+ * import * as assert from "node:assert"
1100
+ * import { isNegative, unsafeFromString } from "effect/BigDecimal"
1101
+ *
1102
+ * assert.deepStrictEqual(isNegative(unsafeFromString("-1")), true)
1103
+ * assert.deepStrictEqual(isNegative(unsafeFromString("0")), false)
1104
+ * assert.deepStrictEqual(isNegative(unsafeFromString("1")), false)
1105
+ * ```
1106
+ *
1107
+ * @since 2.0.0
1108
+ * @category predicates
1109
+ */
1110
+ export const isNegative = (n: BigDecimal): boolean => n.value < bigint0
1111
+
1112
+ /**
1113
+ * Checks if a given `BigDecimal` is positive.
1114
+ *
1115
+ * @example
1116
+ * ```ts
1117
+ * import * as assert from "node:assert"
1118
+ * import { isPositive, unsafeFromString } from "effect/BigDecimal"
1119
+ *
1120
+ * assert.deepStrictEqual(isPositive(unsafeFromString("-1")), false)
1121
+ * assert.deepStrictEqual(isPositive(unsafeFromString("0")), false)
1122
+ * assert.deepStrictEqual(isPositive(unsafeFromString("1")), true)
1123
+ * ```
1124
+ *
1125
+ * @since 2.0.0
1126
+ * @category predicates
1127
+ */
1128
+ export const isPositive = (n: BigDecimal): boolean => n.value > bigint0
1129
+
1130
+ const isBigDecimalArgs = (args: IArguments) => isBigDecimal(args[0])
1131
+
1132
+ /**
1133
+ * Calculate the ceiling of a `BigDecimal` at the given scale.
1134
+ *
1135
+ * @example
1136
+ * ```ts
1137
+ * import * as assert from "node:assert"
1138
+ * import { ceil, unsafeFromString } from "effect/BigDecimal"
1139
+ *
1140
+ * assert.deepStrictEqual(ceil(unsafeFromString("145"), -1), unsafeFromString("150"))
1141
+ * assert.deepStrictEqual(ceil(unsafeFromString("-14.5")), unsafeFromString("-14"))
1142
+ * ```
1143
+ *
1144
+ * @since 3.16.0
1145
+ * @category math
1146
+ */
1147
+ export const ceil: {
1148
+ (scale: number): (self: BigDecimal) => BigDecimal
1149
+ (self: BigDecimal, scale?: number): BigDecimal
1150
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1151
+ const truncated = truncate(self, scale)
1152
+
1153
+ if (isPositive(self) && lessThan(truncated, self)) {
1154
+ return sum(truncated, make(1n, scale))
1155
+ }
1156
+
1157
+ return truncated
1158
+ })
1159
+
1160
+ /**
1161
+ * Calculate the floor of a `BigDecimal` at the given scale.
1162
+ *
1163
+ * @example
1164
+ * ```ts
1165
+ * import * as assert from "node:assert"
1166
+ * import { floor, unsafeFromString } from "effect/BigDecimal"
1167
+ *
1168
+ * assert.deepStrictEqual(floor(unsafeFromString("145"), -1), unsafeFromString("140"))
1169
+ * assert.deepStrictEqual(floor(unsafeFromString("-14.5")), unsafeFromString("-15"))
1170
+ * ```
1171
+ *
1172
+ * @since 3.16.0
1173
+ * @category math
1174
+ */
1175
+ export const floor: {
1176
+ (scale: number): (self: BigDecimal) => BigDecimal
1177
+ (self: BigDecimal, scale?: number): BigDecimal
1178
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1179
+ const truncated = truncate(self, scale)
1180
+
1181
+ if (isNegative(self) && greaterThan(truncated, self)) {
1182
+ return sum(truncated, make(-1n, scale))
1183
+ }
1184
+
1185
+ return truncated
1186
+ })
1187
+
1188
+ /**
1189
+ * Truncate a `BigDecimal` at the given scale. This is the same operation as rounding away from zero.
1190
+ *
1191
+ * @example
1192
+ * ```ts
1193
+ * import * as assert from "node:assert"
1194
+ * import { truncate, unsafeFromString } from "effect/BigDecimal"
1195
+ *
1196
+ * assert.deepStrictEqual(truncate(unsafeFromString("145"), -1), unsafeFromString("140"))
1197
+ * assert.deepStrictEqual(truncate(unsafeFromString("-14.5")), unsafeFromString("-14"))
1198
+ * ```
1199
+ *
1200
+ * @since 3.16.0
1201
+ * @category math
1202
+ */
1203
+ export const truncate: {
1204
+ (scale: number): (self: BigDecimal) => BigDecimal
1205
+ (self: BigDecimal, scale?: number): BigDecimal
1206
+ } = dual(isBigDecimalArgs, (self: BigDecimal, scale: number = 0): BigDecimal => {
1207
+ if (self.scale <= scale) {
1208
+ return self
1209
+ }
1210
+
1211
+ // BigInt division truncates towards zero
1212
+ return make(self.value / (10n ** BigInt(self.scale - scale)), scale)
1213
+ })
1214
+
1215
+ /**
1216
+ * Internal function used by `round` for `half-even` and `half-odd` rounding modes.
1217
+ *
1218
+ * Returns the digit at the position of the given `scale` within the `BigDecimal`.
1219
+ *
1220
+ * @internal
1221
+ */
1222
+ export const digitAt: {
1223
+ (scale: number): (self: BigDecimal) => bigint
1224
+ (self: BigDecimal, scale: number): bigint
1225
+ } = dual(2, (self: BigDecimal, scale: number): bigint => {
1226
+ if (self.scale < scale) {
1227
+ return 0n
1228
+ }
1229
+
1230
+ const scaled = self.value / (10n ** BigInt(self.scale - scale))
1231
+ return scaled % 10n
1232
+ })
1233
+
1234
+ /**
1235
+ * Rounding modes for `BigDecimal`.
1236
+ *
1237
+ * `ceil`: round towards positive infinity
1238
+ * `floor`: round towards negative infinity
1239
+ * `to-zero`: round towards zero
1240
+ * `from-zero`: round away from zero
1241
+ * `half-ceil`: round to the nearest neighbor; if equidistant round towards positive infinity
1242
+ * `half-floor`: round to the nearest neighbor; if equidistant round towards negative infinity
1243
+ * `half-to-zero`: round to the nearest neighbor; if equidistant round towards zero
1244
+ * `half-from-zero`: round to the nearest neighbor; if equidistant round away from zero
1245
+ * `half-even`: round to the nearest neighbor; if equidistant round to the neighbor with an even digit
1246
+ * `half-odd`: round to the nearest neighbor; if equidistant round to the neighbor with an odd digit
1247
+ *
1248
+ * @since 3.16.0
1249
+ * @category math
1250
+ */
1251
+ export type RoundingMode =
1252
+ | "ceil"
1253
+ | "floor"
1254
+ | "to-zero"
1255
+ | "from-zero"
1256
+ | "half-ceil"
1257
+ | "half-floor"
1258
+ | "half-to-zero"
1259
+ | "half-from-zero"
1260
+ | "half-even"
1261
+ | "half-odd"
1262
+
1263
+ /**
1264
+ * Rounds a `BigDecimal` at the given scale with the specified rounding mode.
1265
+ *
1266
+ * @example
1267
+ * ```ts
1268
+ * import * as assert from "node:assert"
1269
+ * import { round, unsafeFromString } from "effect/BigDecimal"
1270
+ *
1271
+ * assert.deepStrictEqual(round(unsafeFromString("145"), { mode: "from-zero", scale: -1 }), unsafeFromString("150"))
1272
+ * assert.deepStrictEqual(round(unsafeFromString("-14.5")), unsafeFromString("-15"))
1273
+ * ```
1274
+ *
1275
+ * @since 3.16.0
1276
+ * @category math
1277
+ */
1278
+ export const round: {
1279
+ (options: { scale?: number; mode?: RoundingMode }): (self: BigDecimal) => BigDecimal
1280
+ (n: BigDecimal, options?: { scale?: number; mode?: RoundingMode }): BigDecimal
1281
+ } = dual(isBigDecimalArgs, (self: BigDecimal, options?: { scale?: number; mode?: RoundingMode }): BigDecimal => {
1282
+ const mode = options?.mode ?? "half-from-zero"
1283
+ const scale = options?.scale ?? 0
1284
+
1285
+ switch (mode) {
1286
+ case "ceil":
1287
+ return ceil(self, scale)
1288
+
1289
+ case "floor":
1290
+ return floor(self, scale)
1291
+
1292
+ case "to-zero":
1293
+ return truncate(self, scale)
1294
+
1295
+ case "from-zero":
1296
+ return (isPositive(self) ? ceil(self, scale) : floor(self, scale))
1297
+
1298
+ case "half-ceil":
1299
+ return floor(sum(self, make(5n, scale + 1)), scale)
1300
+
1301
+ case "half-floor":
1302
+ return ceil(sum(self, make(-5n, scale + 1)), scale)
1303
+
1304
+ case "half-to-zero":
1305
+ return isNegative(self)
1306
+ ? floor(sum(self, make(5n, scale + 1)), scale)
1307
+ : ceil(sum(self, make(-5n, scale + 1)), scale)
1308
+
1309
+ case "half-from-zero":
1310
+ return isNegative(self)
1311
+ ? ceil(sum(self, make(-5n, scale + 1)), scale)
1312
+ : floor(sum(self, make(5n, scale + 1)), scale)
1313
+ }
1314
+
1315
+ const halfCeil = floor(sum(self, make(5n, scale + 1)), scale)
1316
+ const halfFloor = ceil(sum(self, make(-5n, scale + 1)), scale)
1317
+ const digit = digitAt(halfCeil, scale)
1318
+
1319
+ switch (mode) {
1320
+ case "half-even":
1321
+ return equals(halfCeil, halfFloor) ? halfCeil : (digit % 2n === 0n) ? halfCeil : halfFloor
1322
+
1323
+ case "half-odd":
1324
+ return equals(halfCeil, halfFloor) ? halfCeil : (digit % 2n === 0n) ? halfFloor : halfCeil
1325
+ }
1326
+ })
1327
+
1328
+ /**
1329
+ * Takes an `Iterable` of `BigDecimal`s and returns their sum as a single `BigDecimal`
1330
+ *
1331
+ * @example
1332
+ * ```ts
1333
+ * import * as assert from "node:assert"
1334
+ * import { unsafeFromString, sumAll } from "effect/BigDecimal"
1335
+ *
1336
+ * assert.deepStrictEqual(sumAll([unsafeFromString("2"), unsafeFromString("3"), unsafeFromString("4")]), unsafeFromString("9"))
1337
+ * ```
1338
+ *
1339
+ * @category math
1340
+ * @since 3.16.0
1341
+ */
1342
+ export const sumAll = (collection: Iterable<BigDecimal>): BigDecimal => {
1343
+ let out = zero
1344
+ for (const n of collection) {
1345
+ out = sum(out, n)
1346
+ }
1347
+
1348
+ return out
1349
+ }