@yipe/dice 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -816,7 +816,7 @@ declare class PMF {
816
816
  * optionally guarantees at least `minBins` survivors by adding top-K.
817
817
  * Returns a new, non-normalized PMF.
818
818
  */
819
- pruneRelative(epsRel: number, minBins?: number): PMF;
819
+ prune(epsRel: number, minBins?: number): PMF;
820
820
  /** NEW - REVIEW IF THESE ARE USEFUL OR DUPLCIATIVE? */
821
821
  /** Probability mass at exactly x. */
822
822
  pAt(x: number): number;
@@ -881,6 +881,19 @@ declare class PMF {
881
881
  query(): DiceQuery;
882
882
  }
883
883
 
884
+ /** Enable or disable the internal parse cache. */
885
+ declare function setCachingEnabled(enabled: boolean): void;
886
+ /** Returns whether the internal parse cache is currently enabled. */
887
+ declare function getCachingEnabled(): boolean;
888
+ /** Clears the internal parse cache. */
889
+ declare function clearParserCache(): void;
890
+ /**
891
+ * Parse a dice expression into a PMF.
892
+ *
893
+ * - Expression is case-insensitive and ignores spaces.
894
+ */
895
+ declare function parse(expression: string, n?: number): PMF;
896
+
884
897
  /** A labeled mixture builder that preserves provenance in Bin.count. */
885
898
  declare class Mixture<L extends string = string> {
886
899
  private readonly totals;
@@ -917,17 +930,4 @@ declare class Mixture<L extends string = string> {
917
930
  static mix<L extends string = string>(items: Array<[label: L, pmf: PMF, weight: number]>, eps?: number): PMF;
918
931
  }
919
932
 
920
- /** Enable or disable the internal parse cache. */
921
- declare function setCachingEnabled(enabled: boolean): void;
922
- /** Returns whether the internal parse cache is currently enabled. */
923
- declare function getCachingEnabled(): boolean;
924
- /** Clears the internal parse cache. */
925
- declare function clearParserCache(): void;
926
- /**
927
- * Parse a dice expression into a PMF.
928
- *
929
- * - Expression is case-insensitive and ignores spaces.
930
- */
931
- declare function parse(expression: string, n?: number): PMF;
932
-
933
933
  export { type Bin, type DamageDistribution, DiceQuery, EPS, LRUCache, Mixture, type OutcomeLabelMap, type OutcomeSnapshot, type OutcomeType, PMF, type Rounding, type Snapshot, clearParserCache, getCachingEnabled, parse, pmfCache, setCachingEnabled };
package/dist/index.d.ts CHANGED
@@ -816,7 +816,7 @@ declare class PMF {
816
816
  * optionally guarantees at least `minBins` survivors by adding top-K.
817
817
  * Returns a new, non-normalized PMF.
818
818
  */
819
- pruneRelative(epsRel: number, minBins?: number): PMF;
819
+ prune(epsRel: number, minBins?: number): PMF;
820
820
  /** NEW - REVIEW IF THESE ARE USEFUL OR DUPLCIATIVE? */
821
821
  /** Probability mass at exactly x. */
822
822
  pAt(x: number): number;
@@ -881,6 +881,19 @@ declare class PMF {
881
881
  query(): DiceQuery;
882
882
  }
883
883
 
884
+ /** Enable or disable the internal parse cache. */
885
+ declare function setCachingEnabled(enabled: boolean): void;
886
+ /** Returns whether the internal parse cache is currently enabled. */
887
+ declare function getCachingEnabled(): boolean;
888
+ /** Clears the internal parse cache. */
889
+ declare function clearParserCache(): void;
890
+ /**
891
+ * Parse a dice expression into a PMF.
892
+ *
893
+ * - Expression is case-insensitive and ignores spaces.
894
+ */
895
+ declare function parse(expression: string, n?: number): PMF;
896
+
884
897
  /** A labeled mixture builder that preserves provenance in Bin.count. */
885
898
  declare class Mixture<L extends string = string> {
886
899
  private readonly totals;
@@ -917,17 +930,4 @@ declare class Mixture<L extends string = string> {
917
930
  static mix<L extends string = string>(items: Array<[label: L, pmf: PMF, weight: number]>, eps?: number): PMF;
918
931
  }
919
932
 
920
- /** Enable or disable the internal parse cache. */
921
- declare function setCachingEnabled(enabled: boolean): void;
922
- /** Returns whether the internal parse cache is currently enabled. */
923
- declare function getCachingEnabled(): boolean;
924
- /** Clears the internal parse cache. */
925
- declare function clearParserCache(): void;
926
- /**
927
- * Parse a dice expression into a PMF.
928
- *
929
- * - Expression is case-insensitive and ignores spaces.
930
- */
931
- declare function parse(expression: string, n?: number): PMF;
932
-
933
933
  export { type Bin, type DamageDistribution, DiceQuery, EPS, LRUCache, Mixture, type OutcomeLabelMap, type OutcomeSnapshot, type OutcomeType, PMF, type Rounding, type Snapshot, clearParserCache, getCachingEnabled, parse, pmfCache, setCachingEnabled };
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
 
5
- // src/lru-cache.ts
5
+ // src/common/lru-cache.ts
6
6
  var LRUCache = class {
7
7
  constructor(maxSize = 1e3) {
8
8
  this.maxSize = maxSize;
@@ -44,10 +44,10 @@ var LRUCache = class {
44
44
  }
45
45
  };
46
46
 
47
- // src/types.ts
47
+ // src/common/types.ts
48
48
  var EPS = 1e-12;
49
49
 
50
- // src/query.ts
50
+ // src/pmf/query.ts
51
51
  var _DiceQuery = class _DiceQuery {
52
52
  constructor(singles, combined, eps = EPS) {
53
53
  __publicField(this, "singles");
@@ -1909,7 +1909,7 @@ var _PMF = class _PMF {
1909
1909
  * optionally guarantees at least `minBins` survivors by adding top-K.
1910
1910
  * Returns a new, non-normalized PMF.
1911
1911
  */
1912
- pruneRelative(epsRel, minBins = 0) {
1912
+ prune(epsRel, minBins = 0) {
1913
1913
  const size = this.map.size;
1914
1914
  if (size === 0) return this;
1915
1915
  let peak = 0;
@@ -1921,7 +1921,7 @@ var _PMF = class _PMF {
1921
1921
  if (dmg > maxDamage) maxDamage = dmg;
1922
1922
  }
1923
1923
  if (peak === 0)
1924
- return new _PMF(new Map(this.map), this.epsilon, false, this.identifier);
1924
+ return new _PMF(new Map(this.map), epsRel, false, this.identifier);
1925
1925
  const thresh = epsRel * peak;
1926
1926
  const entries = [...this.map.entries()];
1927
1927
  const survivorsByDmg = /* @__PURE__ */ new Map();
@@ -1962,7 +1962,7 @@ var _PMF = class _PMF {
1962
1962
  }
1963
1963
  prunedMap.set(dmg, { p: bin.p, count: newCount, attr: newAttr });
1964
1964
  }
1965
- return new _PMF(prunedMap, this.epsilon, false, `prune(${this.identifier})`);
1965
+ return new _PMF(prunedMap, epsRel, false, `prune(${this.identifier})`);
1966
1966
  }
1967
1967
  /** NEW - REVIEW IF THESE ARE USEFUL OR DUPLCIATIVE? */
1968
1968
  /** Probability mass at exactly x. */
@@ -2186,128 +2186,7 @@ var _PMF = class _PMF {
2186
2186
  __publicField(_PMF, "__anonIdCounter", 1);
2187
2187
  var PMF = _PMF;
2188
2188
 
2189
- // src/mixture.ts
2190
- var Mixture = class _Mixture {
2191
- constructor(eps = EPS) {
2192
- __publicField(this, "totals", /* @__PURE__ */ new Map());
2193
- // raw mass per outcome (pre-normalization)
2194
- __publicField(this, "labelMass", /* @__PURE__ */ new Map());
2195
- // raw mass per outcome per label
2196
- __publicField(this, "eps");
2197
- this.eps = Number.isFinite(eps) ? eps : EPS;
2198
- }
2199
- /** Remove all accumulated state. */
2200
- clear() {
2201
- this.totals.clear();
2202
- this.labelMass.clear();
2203
- return this;
2204
- }
2205
- /** Number of distinct outcome values currently accumulated. */
2206
- size() {
2207
- return this.totals.size;
2208
- }
2209
- /** Whether a label was ever added. */
2210
- hasLabel(label) {
2211
- for (const bag of this.labelMass.values()) if (bag[label]) return true;
2212
- return false;
2213
- }
2214
- /**
2215
- * Add a labeled component with a mixture weight.
2216
- * Weight can be any positive finite number. Very small contributions are pruned by eps.
2217
- */
2218
- add(label, pmf, weight = 1) {
2219
- if (!Number.isFinite(weight) || weight <= 0) return this;
2220
- for (const [v, binOrNumber] of pmf) {
2221
- const isNumber = typeof binOrNumber === "number";
2222
- const p = isNumber ? binOrNumber : binOrNumber?.p ?? 0;
2223
- if (p <= 0) continue;
2224
- const add = weight * p;
2225
- if (!Number.isFinite(add) || Math.abs(add) < this.eps) continue;
2226
- this.totals.set(v, (this.totals.get(v) ?? 0) + add);
2227
- const bag = this.labelMass.get(v) ?? {};
2228
- bag[label] = (bag[label] ?? 0) + add;
2229
- this.labelMass.set(v, bag);
2230
- }
2231
- return this;
2232
- }
2233
- buildPMF(eps = EPS) {
2234
- let grand = 0;
2235
- let c = 0;
2236
- for (const m of this.totals.values()) {
2237
- const y = m - c;
2238
- const t = grand + y;
2239
- c = t - grand - y;
2240
- grand = t;
2241
- }
2242
- if (!(grand > 0)) throw new Error("Mixture: zero total mass");
2243
- const internal = /* @__PURE__ */ new Map();
2244
- for (const [v, m] of this.totals) {
2245
- if (m <= 0 || Math.abs(m) < this.eps) continue;
2246
- const count = this.labelMass.get(v) ?? {};
2247
- internal.set(v, { p: m / grand, count });
2248
- }
2249
- return new PMF(internal, eps);
2250
- }
2251
- /**
2252
- * Produce normalized *per-label* PMFs (labels independent).
2253
- * These are unlabeled PMFs built from the raw mass of that label alone.
2254
- */
2255
- byOutcome() {
2256
- const labels = /* @__PURE__ */ new Set();
2257
- for (const bag of this.labelMass.values()) {
2258
- for (const k of Object.keys(bag)) labels.add(k);
2259
- }
2260
- const out = {};
2261
- for (const label of labels) {
2262
- const m = /* @__PURE__ */ new Map();
2263
- for (const [v, bag] of this.labelMass) {
2264
- const w = bag[label];
2265
- if (w && Math.abs(w) >= this.eps) m.set(v, w);
2266
- }
2267
- if (m.size > 0) out[label] = PMF.fromMap(m, this.eps);
2268
- }
2269
- return out;
2270
- }
2271
- /**
2272
- * Mixture weights per label, normalized to sum to 1 over labels that appeared.
2273
- * Uses raw mass before per-outcome normalization.
2274
- */
2275
- weights() {
2276
- const res = {};
2277
- for (const [, bag] of this.labelMass) {
2278
- for (const [lab, w] of Object.entries(bag)) {
2279
- if (!Number.isFinite(w) || w <= 0) continue;
2280
- res[lab] = (res[lab] ?? 0) + w;
2281
- }
2282
- }
2283
- let total = 0;
2284
- let c = 0;
2285
- for (const v of Object.values(res)) {
2286
- const y = v - c;
2287
- const t = total + y;
2288
- c = t - total - y;
2289
- total = t;
2290
- }
2291
- if (total > 0) {
2292
- for (const k in res) res[k] = res[k] / total;
2293
- }
2294
- return res;
2295
- }
2296
- toJSON() {
2297
- return {
2298
- totals: Array.from(this.totals.entries()).sort((a, b) => a[0] - b[0]),
2299
- labels: Array.from(this.labelMass.entries()).sort((a, b) => a[0] - b[0]),
2300
- eps: this.eps
2301
- };
2302
- }
2303
- static mix(items, eps = EPS) {
2304
- const mix = new _Mixture(eps);
2305
- for (const [lab, pmf, w] of items) mix.add(lab, pmf, w);
2306
- return mix.buildPMF();
2307
- }
2308
- };
2309
-
2310
- // src/dice.ts
2189
+ // src/parser/dice.ts
2311
2190
  var Dice = class _Dice {
2312
2191
  constructor(x = 0) {
2313
2192
  __publicField(this, "faces", {});
@@ -2722,7 +2601,7 @@ var Dice = class _Dice {
2722
2601
  }
2723
2602
  };
2724
2603
 
2725
- // src/parser.ts
2604
+ // src/parser/parser.ts
2726
2605
  var parseCache = new LRUCache(1e3);
2727
2606
  var cachingEnabled = true;
2728
2607
  function setCachingEnabled(enabled) {
@@ -3134,6 +3013,127 @@ function parseOperation(s) {
3134
3013
  return;
3135
3014
  }
3136
3015
 
3016
+ // src/pmf/mixture.ts
3017
+ var Mixture = class _Mixture {
3018
+ constructor(eps = EPS) {
3019
+ __publicField(this, "totals", /* @__PURE__ */ new Map());
3020
+ // raw mass per outcome (pre-normalization)
3021
+ __publicField(this, "labelMass", /* @__PURE__ */ new Map());
3022
+ // raw mass per outcome per label
3023
+ __publicField(this, "eps");
3024
+ this.eps = Number.isFinite(eps) ? eps : EPS;
3025
+ }
3026
+ /** Remove all accumulated state. */
3027
+ clear() {
3028
+ this.totals.clear();
3029
+ this.labelMass.clear();
3030
+ return this;
3031
+ }
3032
+ /** Number of distinct outcome values currently accumulated. */
3033
+ size() {
3034
+ return this.totals.size;
3035
+ }
3036
+ /** Whether a label was ever added. */
3037
+ hasLabel(label) {
3038
+ for (const bag of this.labelMass.values()) if (bag[label]) return true;
3039
+ return false;
3040
+ }
3041
+ /**
3042
+ * Add a labeled component with a mixture weight.
3043
+ * Weight can be any positive finite number. Very small contributions are pruned by eps.
3044
+ */
3045
+ add(label, pmf, weight = 1) {
3046
+ if (!Number.isFinite(weight) || weight <= 0) return this;
3047
+ for (const [v, binOrNumber] of pmf) {
3048
+ const isNumber = typeof binOrNumber === "number";
3049
+ const p = isNumber ? binOrNumber : binOrNumber?.p ?? 0;
3050
+ if (p <= 0) continue;
3051
+ const add = weight * p;
3052
+ if (!Number.isFinite(add) || Math.abs(add) < this.eps) continue;
3053
+ this.totals.set(v, (this.totals.get(v) ?? 0) + add);
3054
+ const bag = this.labelMass.get(v) ?? {};
3055
+ bag[label] = (bag[label] ?? 0) + add;
3056
+ this.labelMass.set(v, bag);
3057
+ }
3058
+ return this;
3059
+ }
3060
+ buildPMF(eps = EPS) {
3061
+ let grand = 0;
3062
+ let c = 0;
3063
+ for (const m of this.totals.values()) {
3064
+ const y = m - c;
3065
+ const t = grand + y;
3066
+ c = t - grand - y;
3067
+ grand = t;
3068
+ }
3069
+ if (!(grand > 0)) throw new Error("Mixture: zero total mass");
3070
+ const internal = /* @__PURE__ */ new Map();
3071
+ for (const [v, m] of this.totals) {
3072
+ if (m <= 0 || Math.abs(m) < this.eps) continue;
3073
+ const count = this.labelMass.get(v) ?? {};
3074
+ internal.set(v, { p: m / grand, count });
3075
+ }
3076
+ return new PMF(internal, eps);
3077
+ }
3078
+ /**
3079
+ * Produce normalized *per-label* PMFs (labels independent).
3080
+ * These are unlabeled PMFs built from the raw mass of that label alone.
3081
+ */
3082
+ byOutcome() {
3083
+ const labels = /* @__PURE__ */ new Set();
3084
+ for (const bag of this.labelMass.values()) {
3085
+ for (const k of Object.keys(bag)) labels.add(k);
3086
+ }
3087
+ const out = {};
3088
+ for (const label of labels) {
3089
+ const m = /* @__PURE__ */ new Map();
3090
+ for (const [v, bag] of this.labelMass) {
3091
+ const w = bag[label];
3092
+ if (w && Math.abs(w) >= this.eps) m.set(v, w);
3093
+ }
3094
+ if (m.size > 0) out[label] = PMF.fromMap(m, this.eps);
3095
+ }
3096
+ return out;
3097
+ }
3098
+ /**
3099
+ * Mixture weights per label, normalized to sum to 1 over labels that appeared.
3100
+ * Uses raw mass before per-outcome normalization.
3101
+ */
3102
+ weights() {
3103
+ const res = {};
3104
+ for (const [, bag] of this.labelMass) {
3105
+ for (const [lab, w] of Object.entries(bag)) {
3106
+ if (!Number.isFinite(w) || w <= 0) continue;
3107
+ res[lab] = (res[lab] ?? 0) + w;
3108
+ }
3109
+ }
3110
+ let total = 0;
3111
+ let c = 0;
3112
+ for (const v of Object.values(res)) {
3113
+ const y = v - c;
3114
+ const t = total + y;
3115
+ c = t - total - y;
3116
+ total = t;
3117
+ }
3118
+ if (total > 0) {
3119
+ for (const k in res) res[k] = res[k] / total;
3120
+ }
3121
+ return res;
3122
+ }
3123
+ toJSON() {
3124
+ return {
3125
+ totals: Array.from(this.totals.entries()).sort((a, b) => a[0] - b[0]),
3126
+ labels: Array.from(this.labelMass.entries()).sort((a, b) => a[0] - b[0]),
3127
+ eps: this.eps
3128
+ };
3129
+ }
3130
+ static mix(items, eps = EPS) {
3131
+ const mix = new _Mixture(eps);
3132
+ for (const [lab, pmf, w] of items) mix.add(lab, pmf, w);
3133
+ return mix.buildPMF();
3134
+ }
3135
+ };
3136
+
3137
3137
  export { DiceQuery, EPS, LRUCache, Mixture, PMF, clearParserCache, getCachingEnabled, parse, pmfCache, setCachingEnabled };
3138
3138
  //# sourceMappingURL=index.js.map
3139
3139
  //# sourceMappingURL=index.js.map