@the-trybe/formula-engine 1.0.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/.claude/settings.local.json +6 -0
- package/PRD_FORMULA_ENGINE.md +1863 -0
- package/README.md +382 -0
- package/dist/decimal-utils.d.ts +180 -0
- package/dist/decimal-utils.js +355 -0
- package/dist/dependency-extractor.d.ts +20 -0
- package/dist/dependency-extractor.js +103 -0
- package/dist/dependency-graph.d.ts +60 -0
- package/dist/dependency-graph.js +252 -0
- package/dist/errors.d.ts +161 -0
- package/dist/errors.js +260 -0
- package/dist/evaluator.d.ts +51 -0
- package/dist/evaluator.js +494 -0
- package/dist/formula-engine.d.ts +79 -0
- package/dist/formula-engine.js +355 -0
- package/dist/functions.d.ts +3 -0
- package/dist/functions.js +720 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +61 -0
- package/dist/lexer.d.ts +25 -0
- package/dist/lexer.js +357 -0
- package/dist/parser.d.ts +32 -0
- package/dist/parser.js +372 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.js +62 -0
- package/jest.config.js +23 -0
- package/package.json +35 -0
- package/src/decimal-utils.ts +408 -0
- package/src/dependency-extractor.ts +117 -0
- package/src/dependency-graph.test.ts +238 -0
- package/src/dependency-graph.ts +288 -0
- package/src/errors.ts +296 -0
- package/src/evaluator.ts +604 -0
- package/src/formula-engine.test.ts +660 -0
- package/src/formula-engine.ts +430 -0
- package/src/functions.ts +770 -0
- package/src/index.ts +103 -0
- package/src/lexer.test.ts +288 -0
- package/src/lexer.ts +394 -0
- package/src/parser.test.ts +349 -0
- package/src/parser.ts +449 -0
- package/src/types.ts +347 -0
- package/tsconfig.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# Formula Engine
|
|
2
|
+
|
|
3
|
+
A configuration-driven expression evaluation system with automatic dependency resolution and arbitrary-precision decimal arithmetic.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Expression Parsing**: Parse mathematical and logical expressions into an AST
|
|
8
|
+
- **Automatic Dependency Resolution**: Extracts dependencies from expressions and evaluates formulas in correct order
|
|
9
|
+
- **Circular Dependency Detection**: Fails fast with helpful error messages when cycles are detected
|
|
10
|
+
- **Decimal Precision**: Uses arbitrary-precision arithmetic to avoid floating-point errors (e.g., `0.1 + 0.2 = 0.3`)
|
|
11
|
+
- **40+ Built-in Functions**: Math, string, logical, aggregation, and type functions
|
|
12
|
+
- **Custom Functions**: Register your own functions
|
|
13
|
+
- **Caching**: AST and dependency caching for improved performance
|
|
14
|
+
- **Type Safety**: Full TypeScript support with comprehensive type definitions
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { FormulaEngine } from 'formula-engine';
|
|
26
|
+
|
|
27
|
+
const engine = new FormulaEngine();
|
|
28
|
+
|
|
29
|
+
// Evaluate a simple expression
|
|
30
|
+
const result = engine.evaluate('$price * $quantity', {
|
|
31
|
+
variables: { price: 19.99, quantity: 3 }
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
console.log(result.value.toString()); // "59.97"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### Single Expression Evaluation
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const engine = new FormulaEngine();
|
|
43
|
+
|
|
44
|
+
// Arithmetic
|
|
45
|
+
engine.evaluate('$a + $b * 2', { variables: { a: 10, b: 5 } });
|
|
46
|
+
// Result: 20
|
|
47
|
+
|
|
48
|
+
// Comparison
|
|
49
|
+
engine.evaluate('$score >= 90', { variables: { score: 85 } });
|
|
50
|
+
// Result: false
|
|
51
|
+
|
|
52
|
+
// Conditional (ternary)
|
|
53
|
+
engine.evaluate('$quantity > 10 ? $price * 0.9 : $price', {
|
|
54
|
+
variables: { quantity: 15, price: 100 }
|
|
55
|
+
});
|
|
56
|
+
// Result: 90
|
|
57
|
+
|
|
58
|
+
// Function calls
|
|
59
|
+
engine.evaluate('ROUND($price * 1.19, 2)', { variables: { price: 99.99 } });
|
|
60
|
+
// Result: 118.99
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Batch Evaluation with Dependencies
|
|
64
|
+
|
|
65
|
+
The engine automatically determines the correct evaluation order:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const formulas = [
|
|
69
|
+
{ id: 'gross', expression: '$unitPrice * $quantity' },
|
|
70
|
+
{ id: 'discount', expression: '$gross * $discountRate' },
|
|
71
|
+
{ id: 'net', expression: '$gross - $discount' },
|
|
72
|
+
{ id: 'tax', expression: '$net * $taxRate' },
|
|
73
|
+
{ id: 'total', expression: '$net + $tax' },
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
const context = {
|
|
77
|
+
variables: {
|
|
78
|
+
unitPrice: 100,
|
|
79
|
+
quantity: 5,
|
|
80
|
+
discountRate: 0.1,
|
|
81
|
+
taxRate: 0.2,
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const results = engine.evaluateAll(formulas, context);
|
|
86
|
+
|
|
87
|
+
// Evaluation order: gross → discount → net → tax → total
|
|
88
|
+
console.log(results.results.get('total')?.value.toString()); // "540"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Decimal Precision
|
|
92
|
+
|
|
93
|
+
JavaScript floating-point math has precision issues:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
// Native JavaScript
|
|
97
|
+
0.1 + 0.2 // 0.30000000000000004 ❌
|
|
98
|
+
|
|
99
|
+
// Formula Engine
|
|
100
|
+
engine.evaluate('0.1 + 0.2', { variables: {} });
|
|
101
|
+
// Result: "0.3" ✓
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Context Variables
|
|
105
|
+
|
|
106
|
+
Use `$` for local variables and `@` for context variables:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
engine.evaluate('$price * (1 + @taxRate)', {
|
|
110
|
+
variables: { price: 100 },
|
|
111
|
+
extra: { taxRate: 0.19 }
|
|
112
|
+
});
|
|
113
|
+
// Result: 119
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Member and Index Access
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Dot notation
|
|
120
|
+
engine.evaluate('$product.price * $product.quantity', {
|
|
121
|
+
variables: {
|
|
122
|
+
product: { price: 25, quantity: 4 }
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Bracket notation
|
|
127
|
+
engine.evaluate('$items[0].name', {
|
|
128
|
+
variables: {
|
|
129
|
+
items: [{ name: 'Widget' }, { name: 'Gadget' }]
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Array Functions
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// SUM with expression
|
|
138
|
+
engine.evaluate('SUM($items, $it.price * $it.qty)', {
|
|
139
|
+
variables: {
|
|
140
|
+
items: [
|
|
141
|
+
{ price: 10, qty: 2 },
|
|
142
|
+
{ price: 20, qty: 1 },
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// Result: 40
|
|
147
|
+
|
|
148
|
+
// FILTER
|
|
149
|
+
engine.evaluate('FILTER($numbers, $it > 5)', {
|
|
150
|
+
variables: { numbers: [1, 3, 7, 9, 2] }
|
|
151
|
+
});
|
|
152
|
+
// Result: [7, 9]
|
|
153
|
+
|
|
154
|
+
// MAP
|
|
155
|
+
engine.evaluate('MAP($prices, $it * 1.1)', {
|
|
156
|
+
variables: { prices: [100, 200, 300] }
|
|
157
|
+
});
|
|
158
|
+
// Result: [110, 220, 330]
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Custom Functions
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
engine.registerFunction({
|
|
165
|
+
name: 'DISCOUNT_TIER',
|
|
166
|
+
minArgs: 2,
|
|
167
|
+
maxArgs: 2,
|
|
168
|
+
returnType: 'decimal',
|
|
169
|
+
implementation: (args) => {
|
|
170
|
+
const [amount, tiers] = args;
|
|
171
|
+
const tier = tiers
|
|
172
|
+
.filter(t => amount >= t.threshold)
|
|
173
|
+
.sort((a, b) => b.threshold - a.threshold)[0];
|
|
174
|
+
return tier ? amount * tier.rate : 0;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
engine.evaluate('DISCOUNT_TIER($total, @tiers)', {
|
|
179
|
+
variables: { total: 150 },
|
|
180
|
+
extra: {
|
|
181
|
+
tiers: [
|
|
182
|
+
{ threshold: 0, rate: 0 },
|
|
183
|
+
{ threshold: 100, rate: 0.05 },
|
|
184
|
+
{ threshold: 200, rate: 0.10 },
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
// Result: 7.5 (150 * 0.05)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Validation
|
|
192
|
+
|
|
193
|
+
Validate formulas before evaluation:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const formulas = [
|
|
197
|
+
{ id: 'a', expression: '$b + 1' },
|
|
198
|
+
{ id: 'b', expression: '$a + 1' }, // Circular!
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
const validation = engine.validate(formulas);
|
|
202
|
+
|
|
203
|
+
if (!validation.valid) {
|
|
204
|
+
console.log(validation.errors);
|
|
205
|
+
// CircularDependencyError: Circular dependency detected: a → b → a
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Built-in Functions
|
|
210
|
+
|
|
211
|
+
### Math Functions
|
|
212
|
+
|
|
213
|
+
| Function | Description | Example |
|
|
214
|
+
|----------|-------------|---------|
|
|
215
|
+
| `ABS(x)` | Absolute value | `ABS(-5)` → `5` |
|
|
216
|
+
| `ROUND(x, p?)` | Round to precision | `ROUND(3.456, 2)` → `3.46` |
|
|
217
|
+
| `FLOOR(x, p?)` | Round down | `FLOOR(3.9)` → `3` |
|
|
218
|
+
| `CEIL(x, p?)` | Round up | `CEIL(3.1)` → `4` |
|
|
219
|
+
| `TRUNCATE(x, p?)` | Truncate decimals | `TRUNCATE(3.999, 2)` → `3.99` |
|
|
220
|
+
| `MIN(a, b, ...)` | Minimum value | `MIN(5, 3, 8)` → `3` |
|
|
221
|
+
| `MAX(a, b, ...)` | Maximum value | `MAX(5, 3, 8)` → `8` |
|
|
222
|
+
| `POW(x, y)` | Power | `POW(2, 3)` → `8` |
|
|
223
|
+
| `SQRT(x)` | Square root | `SQRT(16)` → `4` |
|
|
224
|
+
| `LOG(x)` | Natural logarithm | `LOG(10)` → `2.302...` |
|
|
225
|
+
| `LOG10(x)` | Base-10 logarithm | `LOG10(100)` → `2` |
|
|
226
|
+
| `SIGN(x)` | Sign (-1, 0, 1) | `SIGN(-5)` → `-1` |
|
|
227
|
+
|
|
228
|
+
### String Functions
|
|
229
|
+
|
|
230
|
+
| Function | Description | Example |
|
|
231
|
+
|----------|-------------|---------|
|
|
232
|
+
| `LEN(s)` | String length | `LEN("hello")` → `5` |
|
|
233
|
+
| `UPPER(s)` | Uppercase | `UPPER("hello")` → `"HELLO"` |
|
|
234
|
+
| `LOWER(s)` | Lowercase | `LOWER("HELLO")` → `"hello"` |
|
|
235
|
+
| `TRIM(s)` | Trim whitespace | `TRIM(" hi ")` → `"hi"` |
|
|
236
|
+
| `CONCAT(a, b, ...)` | Concatenate | `CONCAT("a", "b")` → `"ab"` |
|
|
237
|
+
| `SUBSTR(s, start, len?)` | Substring | `SUBSTR("hello", 1, 3)` → `"ell"` |
|
|
238
|
+
| `REPLACE(s, find, rep)` | Replace all | `REPLACE("aaa", "a", "b")` → `"bbb"` |
|
|
239
|
+
| `CONTAINS(s, sub)` | Contains check | `CONTAINS("hello", "ell")` → `true` |
|
|
240
|
+
| `STARTSWITH(s, pre)` | Starts with | `STARTSWITH("hello", "he")` → `true` |
|
|
241
|
+
| `ENDSWITH(s, suf)` | Ends with | `ENDSWITH("hello", "lo")` → `true` |
|
|
242
|
+
|
|
243
|
+
### Logical Functions
|
|
244
|
+
|
|
245
|
+
| Function | Description | Example |
|
|
246
|
+
|----------|-------------|---------|
|
|
247
|
+
| `IF(cond, t, f)` | Conditional | `IF(true, "yes", "no")` → `"yes"` |
|
|
248
|
+
| `COALESCE(a, b, ...)` | First non-null | `COALESCE(null, 5)` → `5` |
|
|
249
|
+
| `ISNULL(x)` | Check null | `ISNULL(null)` → `true` |
|
|
250
|
+
| `ISEMPTY(x)` | Check empty | `ISEMPTY([])` → `true` |
|
|
251
|
+
| `DEFAULT(x, d)` | Default if null | `DEFAULT(null, 0)` → `0` |
|
|
252
|
+
| `AND(a, b, ...)` | Logical AND | `AND(true, false)` → `false` |
|
|
253
|
+
| `OR(a, b, ...)` | Logical OR | `OR(true, false)` → `true` |
|
|
254
|
+
| `NOT(x)` | Logical NOT | `NOT(true)` → `false` |
|
|
255
|
+
|
|
256
|
+
### Aggregation Functions
|
|
257
|
+
|
|
258
|
+
| Function | Description | Example |
|
|
259
|
+
|----------|-------------|---------|
|
|
260
|
+
| `SUM(arr)` | Sum of array | `SUM([1, 2, 3])` → `6` |
|
|
261
|
+
| `SUM(arr, expr)` | Sum with expression | `SUM($items, $it.price)` |
|
|
262
|
+
| `AVG(arr)` | Average | `AVG([10, 20, 30])` → `20` |
|
|
263
|
+
| `COUNT(arr)` | Count elements | `COUNT([1, 2, 3])` → `3` |
|
|
264
|
+
| `PRODUCT(arr)` | Product of values | `PRODUCT([2, 3, 4])` → `24` |
|
|
265
|
+
| `FILTER(arr, cond)` | Filter array | `FILTER($arr, $it > 5)` |
|
|
266
|
+
| `MAP(arr, expr)` | Transform array | `MAP($arr, $it * 2)` |
|
|
267
|
+
| `FIRST(arr)` | First element | `FIRST([1, 2, 3])` → `1` |
|
|
268
|
+
| `LAST(arr)` | Last element | `LAST([1, 2, 3])` → `3` |
|
|
269
|
+
|
|
270
|
+
### Type Functions
|
|
271
|
+
|
|
272
|
+
| Function | Description | Example |
|
|
273
|
+
|----------|-------------|---------|
|
|
274
|
+
| `NUMBER(x)` | Convert to number | `NUMBER("42")` → `42` |
|
|
275
|
+
| `STRING(x)` | Convert to string | `STRING(42)` → `"42"` |
|
|
276
|
+
| `BOOLEAN(x)` | Convert to boolean | `BOOLEAN(1)` → `true` |
|
|
277
|
+
| `TYPEOF(x)` | Get type name | `TYPEOF(42)` → `"decimal"` |
|
|
278
|
+
|
|
279
|
+
## Configuration
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
const engine = new FormulaEngine({
|
|
283
|
+
// Enable expression caching (default: true)
|
|
284
|
+
enableCache: true,
|
|
285
|
+
|
|
286
|
+
// Maximum cache size (default: 1000)
|
|
287
|
+
maxCacheSize: 1000,
|
|
288
|
+
|
|
289
|
+
// Strict mode - fail on undefined variables (default: true)
|
|
290
|
+
strictMode: true,
|
|
291
|
+
|
|
292
|
+
// Decimal configuration
|
|
293
|
+
decimal: {
|
|
294
|
+
precision: 20, // Significant digits
|
|
295
|
+
roundingMode: 'HALF_UP', // Rounding mode
|
|
296
|
+
divisionScale: 10, // Decimal places for division
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
// Security limits
|
|
300
|
+
security: {
|
|
301
|
+
maxExpressionLength: 10000,
|
|
302
|
+
maxRecursionDepth: 100,
|
|
303
|
+
maxIterations: 10000,
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Error Handling
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const result = engine.evaluate('$a / $b', {
|
|
312
|
+
variables: { a: 10, b: 0 }
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if (!result.success) {
|
|
316
|
+
console.log(result.error); // DivisionByZeroError
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Error Types
|
|
321
|
+
|
|
322
|
+
- **Parse Errors**: `SyntaxError`, `UnexpectedTokenError`, `UnterminatedStringError`
|
|
323
|
+
- **Validation Errors**: `CircularDependencyError`, `UndefinedVariableError`, `UndefinedFunctionError`
|
|
324
|
+
- **Evaluation Errors**: `DivisionByZeroError`, `TypeMismatchError`, `ArgumentCountError`
|
|
325
|
+
|
|
326
|
+
## API Reference
|
|
327
|
+
|
|
328
|
+
### FormulaEngine
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
class FormulaEngine {
|
|
332
|
+
constructor(config?: FormulaEngineConfig);
|
|
333
|
+
|
|
334
|
+
// Parse expression to AST
|
|
335
|
+
parse(expression: string): ASTNode;
|
|
336
|
+
|
|
337
|
+
// Extract dependencies from expression
|
|
338
|
+
extractDependencies(expression: string): Set<string>;
|
|
339
|
+
|
|
340
|
+
// Build dependency graph
|
|
341
|
+
buildDependencyGraph(formulas: FormulaDefinition[]): DependencyGraph;
|
|
342
|
+
|
|
343
|
+
// Get evaluation order
|
|
344
|
+
getEvaluationOrder(formulas: FormulaDefinition[]): string[];
|
|
345
|
+
|
|
346
|
+
// Validate formulas
|
|
347
|
+
validate(formulas: FormulaDefinition[]): ValidationResult;
|
|
348
|
+
|
|
349
|
+
// Evaluate single expression
|
|
350
|
+
evaluate(expression: string, context: EvaluationContext): EvaluationResult;
|
|
351
|
+
|
|
352
|
+
// Evaluate all formulas in order
|
|
353
|
+
evaluateAll(formulas: FormulaDefinition[], context: EvaluationContext): EvaluationResultSet;
|
|
354
|
+
|
|
355
|
+
// Register custom function
|
|
356
|
+
registerFunction(definition: FunctionDefinition): void;
|
|
357
|
+
|
|
358
|
+
// Cache management
|
|
359
|
+
clearCache(): void;
|
|
360
|
+
getCacheStats(): CacheStats;
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Development
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
# Run tests
|
|
368
|
+
npm test
|
|
369
|
+
|
|
370
|
+
# Run tests with coverage
|
|
371
|
+
npm run test:coverage
|
|
372
|
+
|
|
373
|
+
# Build
|
|
374
|
+
npm run build
|
|
375
|
+
|
|
376
|
+
# Lint
|
|
377
|
+
npm run lint
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
MIT
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import Decimal from 'decimal.js';
|
|
2
|
+
import { DecimalConfig, DecimalRoundingMode } from './types';
|
|
3
|
+
export type DecimalLike = Decimal | string | number | bigint;
|
|
4
|
+
export interface DecimalUtilsConfig {
|
|
5
|
+
precision: number;
|
|
6
|
+
roundingMode: DecimalRoundingMode;
|
|
7
|
+
divisionScale: number;
|
|
8
|
+
maxExponent: number;
|
|
9
|
+
minExponent: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class DecimalUtils {
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config?: Partial<DecimalConfig>);
|
|
14
|
+
/**
|
|
15
|
+
* Create a Decimal from various input types
|
|
16
|
+
*/
|
|
17
|
+
from(value: DecimalLike): Decimal;
|
|
18
|
+
/**
|
|
19
|
+
* Check if a value is a Decimal
|
|
20
|
+
*/
|
|
21
|
+
isDecimal(value: unknown): value is Decimal;
|
|
22
|
+
/**
|
|
23
|
+
* Convert a value to Decimal if it's numeric
|
|
24
|
+
*/
|
|
25
|
+
toDecimal(value: unknown): Decimal | unknown;
|
|
26
|
+
/**
|
|
27
|
+
* Addition
|
|
28
|
+
*/
|
|
29
|
+
add(a: DecimalLike, b: DecimalLike): Decimal;
|
|
30
|
+
/**
|
|
31
|
+
* Subtraction
|
|
32
|
+
*/
|
|
33
|
+
subtract(a: DecimalLike, b: DecimalLike): Decimal;
|
|
34
|
+
/**
|
|
35
|
+
* Multiplication
|
|
36
|
+
*/
|
|
37
|
+
multiply(a: DecimalLike, b: DecimalLike): Decimal;
|
|
38
|
+
/**
|
|
39
|
+
* Division with scale
|
|
40
|
+
*/
|
|
41
|
+
divide(a: DecimalLike, b: DecimalLike, scale?: number, roundingMode?: DecimalRoundingMode): Decimal;
|
|
42
|
+
/**
|
|
43
|
+
* Modulo
|
|
44
|
+
*/
|
|
45
|
+
modulo(a: DecimalLike, b: DecimalLike): Decimal;
|
|
46
|
+
/**
|
|
47
|
+
* Power
|
|
48
|
+
*/
|
|
49
|
+
power(base: DecimalLike, exponent: number): Decimal;
|
|
50
|
+
/**
|
|
51
|
+
* Negation
|
|
52
|
+
*/
|
|
53
|
+
negate(value: DecimalLike): Decimal;
|
|
54
|
+
/**
|
|
55
|
+
* Absolute value
|
|
56
|
+
*/
|
|
57
|
+
abs(value: DecimalLike): Decimal;
|
|
58
|
+
/**
|
|
59
|
+
* Round to specified decimal places
|
|
60
|
+
*/
|
|
61
|
+
round(value: DecimalLike, scale: number, roundingMode?: DecimalRoundingMode): Decimal;
|
|
62
|
+
/**
|
|
63
|
+
* Floor to specified decimal places
|
|
64
|
+
*/
|
|
65
|
+
floor(value: DecimalLike, scale?: number): Decimal;
|
|
66
|
+
/**
|
|
67
|
+
* Ceiling to specified decimal places
|
|
68
|
+
*/
|
|
69
|
+
ceil(value: DecimalLike, scale?: number): Decimal;
|
|
70
|
+
/**
|
|
71
|
+
* Truncate to specified decimal places
|
|
72
|
+
*/
|
|
73
|
+
truncate(value: DecimalLike, scale?: number): Decimal;
|
|
74
|
+
/**
|
|
75
|
+
* Square root
|
|
76
|
+
*/
|
|
77
|
+
sqrt(value: DecimalLike): Decimal;
|
|
78
|
+
/**
|
|
79
|
+
* Natural logarithm
|
|
80
|
+
*/
|
|
81
|
+
ln(value: DecimalLike): Decimal;
|
|
82
|
+
/**
|
|
83
|
+
* Base-10 logarithm
|
|
84
|
+
*/
|
|
85
|
+
log10(value: DecimalLike): Decimal;
|
|
86
|
+
/**
|
|
87
|
+
* Comparison: returns -1, 0, or 1
|
|
88
|
+
*/
|
|
89
|
+
compare(a: DecimalLike, b: DecimalLike): -1 | 0 | 1;
|
|
90
|
+
/**
|
|
91
|
+
* Equality check
|
|
92
|
+
*/
|
|
93
|
+
equals(a: DecimalLike, b: DecimalLike): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Greater than
|
|
96
|
+
*/
|
|
97
|
+
greaterThan(a: DecimalLike, b: DecimalLike): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Greater than or equal
|
|
100
|
+
*/
|
|
101
|
+
greaterThanOrEqual(a: DecimalLike, b: DecimalLike): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Less than
|
|
104
|
+
*/
|
|
105
|
+
lessThan(a: DecimalLike, b: DecimalLike): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Less than or equal
|
|
108
|
+
*/
|
|
109
|
+
lessThanOrEqual(a: DecimalLike, b: DecimalLike): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Check if zero
|
|
112
|
+
*/
|
|
113
|
+
isZero(value: DecimalLike): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Check if positive
|
|
116
|
+
*/
|
|
117
|
+
isPositive(value: DecimalLike): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Check if negative
|
|
120
|
+
*/
|
|
121
|
+
isNegative(value: DecimalLike): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Check if integer
|
|
124
|
+
*/
|
|
125
|
+
isInteger(value: DecimalLike): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Get sign: -1, 0, or 1
|
|
128
|
+
*/
|
|
129
|
+
sign(value: DecimalLike): -1 | 0 | 1;
|
|
130
|
+
/**
|
|
131
|
+
* Get precision (total significant digits)
|
|
132
|
+
*/
|
|
133
|
+
precision(value: DecimalLike): number;
|
|
134
|
+
/**
|
|
135
|
+
* Get scale (decimal places)
|
|
136
|
+
*/
|
|
137
|
+
scale(value: DecimalLike): number;
|
|
138
|
+
/**
|
|
139
|
+
* Convert to JavaScript number (may lose precision)
|
|
140
|
+
*/
|
|
141
|
+
toNumber(value: DecimalLike): number;
|
|
142
|
+
/**
|
|
143
|
+
* Convert to string
|
|
144
|
+
*/
|
|
145
|
+
toString(value: DecimalLike): string;
|
|
146
|
+
/**
|
|
147
|
+
* Convert to fixed decimal places string
|
|
148
|
+
*/
|
|
149
|
+
toFixed(value: DecimalLike, scale: number): string;
|
|
150
|
+
/**
|
|
151
|
+
* Minimum of values
|
|
152
|
+
*/
|
|
153
|
+
min(...values: DecimalLike[]): Decimal;
|
|
154
|
+
/**
|
|
155
|
+
* Maximum of values
|
|
156
|
+
*/
|
|
157
|
+
max(...values: DecimalLike[]): Decimal;
|
|
158
|
+
/**
|
|
159
|
+
* Sum of values
|
|
160
|
+
*/
|
|
161
|
+
sum(values: DecimalLike[]): Decimal;
|
|
162
|
+
/**
|
|
163
|
+
* Average of values
|
|
164
|
+
*/
|
|
165
|
+
avg(values: DecimalLike[]): Decimal;
|
|
166
|
+
/**
|
|
167
|
+
* Product of values
|
|
168
|
+
*/
|
|
169
|
+
product(values: DecimalLike[]): Decimal;
|
|
170
|
+
/**
|
|
171
|
+
* Create zero
|
|
172
|
+
*/
|
|
173
|
+
zero(): Decimal;
|
|
174
|
+
/**
|
|
175
|
+
* Create one
|
|
176
|
+
*/
|
|
177
|
+
one(): Decimal;
|
|
178
|
+
}
|
|
179
|
+
export declare const decimalUtils: DecimalUtils;
|
|
180
|
+
export { Decimal };
|