@obinexusmk2/hypernum 0.1.0 → 0.1.1

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 (140) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +355 -256
  3. package/dist/index.cjs +4 -8
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.js +4 -7
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.umd.js +2 -2
  9. package/dist/index.umd.js.map +1 -1
  10. package/dist/types/{config → src/config}/config-loader.d.ts +0 -0
  11. package/dist/types/src/config/config-loader.d.ts.map +1 -0
  12. package/dist/types/{config → src/config}/config-parser.d.ts +0 -0
  13. package/dist/types/src/config/config-parser.d.ts.map +1 -0
  14. package/dist/types/{config → src/config}/config-resolver.d.ts +0 -0
  15. package/dist/types/src/config/config-resolver.d.ts.map +1 -0
  16. package/dist/types/{config → src/config}/config-source.d.ts +0 -0
  17. package/dist/types/src/config/config-source.d.ts.map +1 -0
  18. package/dist/types/{config → src/config}/index.d.ts +0 -0
  19. package/dist/types/src/config/index.d.ts.map +1 -0
  20. package/dist/types/{core → src/core}/common.d.ts +0 -0
  21. package/dist/types/src/core/common.d.ts.map +1 -0
  22. package/dist/types/{core → src/core}/config.d.ts +0 -0
  23. package/dist/types/src/core/config.d.ts.map +1 -0
  24. package/dist/types/{core → src/core}/constants.d.ts +0 -0
  25. package/dist/types/src/core/constants.d.ts.map +1 -0
  26. package/dist/types/{core → src/core}/errors.d.ts +0 -0
  27. package/dist/types/src/core/errors.d.ts.map +1 -0
  28. package/dist/types/{core → src/core}/hypernum.d.ts +0 -0
  29. package/dist/types/src/core/hypernum.d.ts.map +1 -0
  30. package/dist/types/{core → src/core}/index.d.ts +0 -0
  31. package/dist/types/src/core/index.d.ts.map +1 -0
  32. package/dist/types/{index.d.ts → src/index.d.ts} +1 -1
  33. package/dist/types/src/index.d.ts.map +1 -0
  34. package/dist/types/{operations → src/operations}/arithmetic.d.ts +0 -0
  35. package/dist/types/src/operations/arithmetic.d.ts.map +1 -0
  36. package/dist/types/{operations → src/operations}/bitwise.d.ts +0 -0
  37. package/dist/types/src/operations/bitwise.d.ts.map +1 -0
  38. package/dist/types/{operations → src/operations}/comparison.d.ts +0 -0
  39. package/dist/types/src/operations/comparison.d.ts.map +1 -0
  40. package/dist/types/{operations → src/operations}/conversion.d.ts +0 -0
  41. package/dist/types/src/operations/conversion.d.ts.map +1 -0
  42. package/dist/types/{operations → src/operations}/factorial.d.ts +0 -0
  43. package/dist/types/src/operations/factorial.d.ts.map +1 -0
  44. package/dist/types/{operations → src/operations}/index.d.ts +0 -0
  45. package/dist/types/src/operations/index.d.ts.map +1 -0
  46. package/dist/types/{operations → src/operations}/power.d.ts +0 -0
  47. package/dist/types/src/operations/power.d.ts.map +1 -0
  48. package/dist/types/{storage → src/storage}/Heap.d.ts +0 -0
  49. package/dist/types/src/storage/Heap.d.ts.map +1 -0
  50. package/dist/types/{storage → src/storage}/index.d.ts +0 -0
  51. package/dist/types/src/storage/index.d.ts.map +1 -0
  52. package/dist/types/{structures → src/structures}/ackermann.d.ts +0 -0
  53. package/dist/types/src/structures/ackermann.d.ts.map +1 -0
  54. package/dist/types/{structures → src/structures}/big-array.d.ts +0 -0
  55. package/dist/types/src/structures/big-array.d.ts.map +1 -0
  56. package/dist/types/{structures → src/structures}/index.d.ts +0 -0
  57. package/dist/types/src/structures/index.d.ts.map +1 -0
  58. package/dist/types/{structures → src/structures}/number-tree.d.ts +0 -0
  59. package/dist/types/src/structures/number-tree.d.ts.map +1 -0
  60. package/dist/types/{structures → src/structures}/power-tower.d.ts +0 -0
  61. package/dist/types/src/structures/power-tower.d.ts.map +1 -0
  62. package/dist/types/{utils → src/utils}/formatting.d.ts +0 -0
  63. package/dist/types/src/utils/formatting.d.ts.map +1 -0
  64. package/dist/types/{utils → src/utils}/index.d.ts +0 -0
  65. package/dist/types/src/utils/index.d.ts.map +1 -0
  66. package/dist/types/{utils → src/utils}/parser.d.ts +0 -0
  67. package/dist/types/src/utils/parser.d.ts.map +1 -0
  68. package/dist/types/{utils → src/utils}/precision.d.ts +0 -0
  69. package/dist/types/src/utils/precision.d.ts.map +1 -0
  70. package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
  71. package/dist/types/src/utils/validation.d.ts.map +1 -0
  72. package/package.json +169 -164
  73. package/rollup.config.js +163 -161
  74. package/src/cli/hypernum.js +272 -0
  75. package/src/config/config-loader.ts +0 -0
  76. package/src/config/config-parser.ts +160 -160
  77. package/src/config/config-resolver.ts +0 -0
  78. package/src/config/config-source.ts +0 -0
  79. package/src/config/index.ts +0 -0
  80. package/src/core/common.ts +184 -184
  81. package/src/core/config.ts +392 -392
  82. package/src/core/constants.ts +101 -101
  83. package/src/core/errors.ts +202 -202
  84. package/src/core/hypernum.ts +240 -240
  85. package/src/core/index.ts +4 -4
  86. package/src/index.ts +179 -182
  87. package/src/operations/arithmetic.ts +332 -332
  88. package/src/operations/bitwise.ts +366 -366
  89. package/src/operations/comparison.ts +271 -271
  90. package/src/operations/conversion.ts +399 -399
  91. package/src/operations/factorial.ts +278 -278
  92. package/src/operations/index.ts +4 -4
  93. package/src/operations/power.ts +315 -315
  94. package/src/storage/Heap.ts +237 -237
  95. package/src/storage/index.ts +0 -0
  96. package/src/structures/ackermann.ts +232 -232
  97. package/src/structures/big-array.ts +305 -305
  98. package/src/structures/index.ts +3 -3
  99. package/src/structures/number-tree.ts +403 -403
  100. package/src/structures/power-tower.ts +277 -277
  101. package/src/types/common.d.ts +356 -356
  102. package/src/types/core.d.ts +160 -160
  103. package/src/types/index.d.ts +1 -1
  104. package/src/utils/formatting.ts +245 -245
  105. package/src/utils/index.ts +4 -4
  106. package/src/utils/parser.ts +244 -244
  107. package/src/utils/precision.ts +216 -216
  108. package/src/utils/validation.ts +182 -182
  109. package/tsconfig.json +83 -83
  110. package/dist/types/config/config-loader.d.ts.map +0 -1
  111. package/dist/types/config/config-parser.d.ts.map +0 -1
  112. package/dist/types/config/config-resolver.d.ts.map +0 -1
  113. package/dist/types/config/config-source.d.ts.map +0 -1
  114. package/dist/types/config/index.d.ts.map +0 -1
  115. package/dist/types/core/common.d.ts.map +0 -1
  116. package/dist/types/core/config.d.ts.map +0 -1
  117. package/dist/types/core/constants.d.ts.map +0 -1
  118. package/dist/types/core/errors.d.ts.map +0 -1
  119. package/dist/types/core/hypernum.d.ts.map +0 -1
  120. package/dist/types/core/index.d.ts.map +0 -1
  121. package/dist/types/index.d.ts.map +0 -1
  122. package/dist/types/operations/arithmetic.d.ts.map +0 -1
  123. package/dist/types/operations/bitwise.d.ts.map +0 -1
  124. package/dist/types/operations/comparison.d.ts.map +0 -1
  125. package/dist/types/operations/conversion.d.ts.map +0 -1
  126. package/dist/types/operations/factorial.d.ts.map +0 -1
  127. package/dist/types/operations/index.d.ts.map +0 -1
  128. package/dist/types/operations/power.d.ts.map +0 -1
  129. package/dist/types/storage/Heap.d.ts.map +0 -1
  130. package/dist/types/storage/index.d.ts.map +0 -1
  131. package/dist/types/structures/ackermann.d.ts.map +0 -1
  132. package/dist/types/structures/big-array.d.ts.map +0 -1
  133. package/dist/types/structures/index.d.ts.map +0 -1
  134. package/dist/types/structures/number-tree.d.ts.map +0 -1
  135. package/dist/types/structures/power-tower.d.ts.map +0 -1
  136. package/dist/types/utils/formatting.d.ts.map +0 -1
  137. package/dist/types/utils/index.d.ts.map +0 -1
  138. package/dist/types/utils/parser.d.ts.map +0 -1
  139. package/dist/types/utils/precision.d.ts.map +0 -1
  140. package/dist/types/utils/validation.d.ts.map +0 -1
@@ -1,245 +1,245 @@
1
- /**
2
- * Parser utilities for Hypernum library
3
- * Provides functions for parsing various number formats and notations
4
- */
5
-
6
- import { ValidationError } from './validation';
7
- import { RoundingMode } from './precision';
8
-
9
- /**
10
- * Supported number format types
11
- */
12
- export enum NumberFormat {
13
- STANDARD = 'STANDARD', // Regular decimal notation
14
- SCIENTIFIC = 'SCIENTIFIC', // Scientific notation (e.g., 1.23e4)
15
- ENGINEERING = 'ENGINEERING', // Engineering notation (e.g., 1.23e6)
16
- COMPACT = 'COMPACT', // Compact notation with suffixes (e.g., 1.23M)
17
- FRACTION = 'FRACTION', // Fractional notation (e.g., 1/3)
18
- PERCENTAGE = 'PERCENTAGE', // Percentage notation (e.g., 12.3%)
19
- HEXADECIMAL = 'HEXADECIMAL', // Hex notation (e.g., 0xFF)
20
- BINARY = 'BINARY', // Binary notation (e.g., 0b1010)
21
- OCTAL = 'OCTAL' // Octal notation (e.g., 0o777)
22
- }
23
-
24
- /**
25
- * Options for parsing numbers
26
- */
27
- export interface ParseOptions {
28
- format?: NumberFormat;
29
- base?: number;
30
- allowFractions?: boolean;
31
- rounding?: RoundingMode;
32
- precision?: number;
33
- strict?: boolean;
34
- }
35
-
36
- const DEFAULT_PARSE_OPTIONS: Required<ParseOptions> = {
37
- format: NumberFormat.STANDARD,
38
- base: 10,
39
- allowFractions: false,
40
- rounding: RoundingMode.HALF_EVEN,
41
- precision: 0,
42
- strict: true
43
- };
44
-
45
- /**
46
- * Parse any supported number format to BigInt
47
- */
48
- export const parseNumber = (input: string, options: ParseOptions = {}): bigint => {
49
- const opts: Required<ParseOptions> = { ...DEFAULT_PARSE_OPTIONS, ...options };
50
-
51
- // Remove whitespace if not in strict mode
52
- const str = opts.strict ? input : input.trim();
53
-
54
- if (str === '') {
55
- throw new ValidationError('Empty string cannot be parsed as a number');
56
- }
57
-
58
- try {
59
- switch (opts.format) {
60
- case NumberFormat.SCIENTIFIC:
61
- case NumberFormat.ENGINEERING:
62
- return parseScientificNotation(str);
63
- case NumberFormat.COMPACT:
64
- return parseCompactNotation(str);
65
- case NumberFormat.FRACTION:
66
- return parseFraction(str, opts.rounding, opts.precision);
67
- case NumberFormat.PERCENTAGE:
68
- return parsePercentage(str);
69
- case NumberFormat.HEXADECIMAL:
70
- return parseBaseNotation(str, 16);
71
- case NumberFormat.BINARY:
72
- return parseBaseNotation(str, 2);
73
- case NumberFormat.OCTAL:
74
- return parseBaseNotation(str, 8);
75
- default:
76
- return parseStandardNotation(str);
77
- }
78
- } catch (error) {
79
- if (error instanceof ValidationError) {
80
- throw error;
81
- }
82
- throw new ValidationError(`Failed to parse number: ${input}`);
83
- }
84
- };
85
-
86
- /**
87
- * Parse standard decimal notation
88
- */
89
- const parseStandardNotation = (str: string): bigint => {
90
- // Remove commas and validate format
91
- const cleanStr = str.replace(/,/g, '');
92
- if (!/^-?\d+$/.test(cleanStr)) {
93
- throw new ValidationError('Invalid standard notation format');
94
- }
95
-
96
- return BigInt(cleanStr);
97
- };
98
-
99
- /**
100
- * Parse scientific notation (e.g., 1.23e4)
101
- */
102
- const parseScientificNotation = (str: string): bigint => {
103
- const match = str.match(/^(-?\d*\.?\d+)e([+-]?\d+)$/i);
104
- if (!match) {
105
- throw new ValidationError('Invalid scientific notation format');
106
- }
107
-
108
- const [, coefficient, exponent] = match;
109
- if (!coefficient) {
110
- throw new ValidationError('Invalid scientific notation format');
111
- }
112
- const [intPart, fracPart = ''] = coefficient.split('.');
113
- const normalizedCoef = intPart + fracPart;
114
- const adjustedExp = parseInt(exponent || '0') - fracPart.length;
115
-
116
- if (adjustedExp >= 0) {
117
- return BigInt(normalizedCoef) * (BigInt(10) ** BigInt(adjustedExp));
118
- } else {
119
- return BigInt(normalizedCoef) / (BigInt(10) ** BigInt(-adjustedExp));
120
- }
121
- };
122
-
123
- /**
124
- * Parse compact notation with suffixes (e.g., 1.23M)
125
- */
126
- const parseCompactNotation = (str: string): bigint => {
127
- const match = str.match(/^(-?\d*\.?\d+)\s*([KMBTQ])$/i);
128
- if (!match) {
129
- throw new ValidationError('Invalid compact notation format');
130
- }
131
-
132
- const [, number, suffix] = match;
133
- const value = parseFloat(number || '0');
134
-
135
- const multipliers = {
136
- K: 1000n,
137
- M: 1000000n,
138
- B: 1000000000n,
139
- T: 1000000000000n,
140
- Q: 1000000000000000n
141
- };
142
-
143
- if (!suffix) {
144
- throw new ValidationError('Invalid compact notation format');
145
- }
146
-
147
- const multiplier = multipliers[suffix.toUpperCase() as keyof typeof multipliers];
148
- return BigInt(Math.round(value * Number(multiplier)));
149
- };
150
-
151
- /**
152
- * Parse fraction notation (e.g., 1/3)
153
- */
154
- const parseFraction = (
155
- str: string,
156
- rounding: RoundingMode = RoundingMode.HALF_EVEN,
157
- precision: number = 0
158
- ): bigint => {
159
- const [numerator, denominator] = str.split('/');
160
- if (!numerator || !denominator) {
161
- throw new ValidationError('Invalid fraction format');
162
- }
163
-
164
- const num = BigInt(numerator);
165
- const den = BigInt(denominator);
166
-
167
- if (den === 0n) {
168
- throw new ValidationError('Division by zero in fraction');
169
- }
170
-
171
- const scale = BigInt(10) ** BigInt(precision);
172
- const scaledResult = (num * scale) / den;
173
-
174
- // Apply rounding if needed
175
- if (rounding === RoundingMode.FLOOR) {
176
- return scaledResult;
177
- } else if (rounding === RoundingMode.CEIL) {
178
- return scaledResult + (num * scale % den === 0n ? 0n : 1n);
179
- }
180
-
181
- return scaledResult;
182
- };
183
-
184
- /**
185
- * Parse percentage notation (e.g., 12.3%)
186
- */
187
- const parsePercentage = (str: string): bigint => {
188
- const match = str.match(/^(-?\d*\.?\d+)%$/);
189
- if (!match) {
190
- throw new ValidationError('Invalid percentage format');
191
- }
192
-
193
- const value = parseFloat(match[1] || '0');
194
- return BigInt(Math.round(value * 100));
195
- };
196
-
197
- /**
198
- * Parse number in different bases (binary, octal, hex)
199
- */
200
- const parseBaseNotation = (str: string, base: number): bigint => {
201
- let cleanStr = str.toLowerCase();
202
-
203
- // Remove prefix if present
204
- const prefixes: Record<number, string> = {
205
- 2: '0b',
206
- 8: '0o',
207
- 16: '0x'
208
- };
209
-
210
- const prefix = prefixes[base];
211
- if (prefix && cleanStr.startsWith(prefix)) {
212
- cleanStr = cleanStr.slice(2);
213
- }
214
-
215
- // Validate characters based on base
216
- const validChars = {
217
- 2: /^[01]+$/,
218
- 8: /^[0-7]+$/,
219
- 16: /^[0-9a-f]+$/
220
- };
221
-
222
- if (!validChars[base as keyof typeof validChars].test(cleanStr)) {
223
- throw new ValidationError(`Invalid ${base}-base number format`);
224
- }
225
-
226
- return BigInt(`0${prefixes[base]}${cleanStr}`);
227
- };
228
-
229
- /**
230
- * Detect number format from string
231
- */
232
- export const detectNumberFormat = (str: string): NumberFormat => {
233
- const cleanStr = str.trim();
234
-
235
- if (/^-?\d+$/.test(cleanStr)) return NumberFormat.STANDARD;
236
- if (/^-?\d*\.?\d+e[+-]?\d+$/i.test(cleanStr)) return NumberFormat.SCIENTIFIC;
237
- if (/^-?\d*\.?\d+[KMBTQ]$/i.test(cleanStr)) return NumberFormat.COMPACT;
238
- if (/^-?\d+\/\d+$/.test(cleanStr)) return NumberFormat.FRACTION;
239
- if (/^-?\d*\.?\d+%$/.test(cleanStr)) return NumberFormat.PERCENTAGE;
240
- if (/^(0x|0X)[0-9a-fA-F]+$/.test(cleanStr)) return NumberFormat.HEXADECIMAL;
241
- if (/^(0b|0B)[01]+$/.test(cleanStr)) return NumberFormat.BINARY;
242
- if (/^(0o|0O)[0-7]+$/.test(cleanStr)) return NumberFormat.OCTAL;
243
-
244
- throw new ValidationError('Unable to detect number format');
1
+ /**
2
+ * Parser utilities for Hypernum library
3
+ * Provides functions for parsing various number formats and notations
4
+ */
5
+
6
+ import { ValidationError } from './validation';
7
+ import { RoundingMode } from './precision';
8
+
9
+ /**
10
+ * Supported number format types
11
+ */
12
+ export enum NumberFormat {
13
+ STANDARD = 'STANDARD', // Regular decimal notation
14
+ SCIENTIFIC = 'SCIENTIFIC', // Scientific notation (e.g., 1.23e4)
15
+ ENGINEERING = 'ENGINEERING', // Engineering notation (e.g., 1.23e6)
16
+ COMPACT = 'COMPACT', // Compact notation with suffixes (e.g., 1.23M)
17
+ FRACTION = 'FRACTION', // Fractional notation (e.g., 1/3)
18
+ PERCENTAGE = 'PERCENTAGE', // Percentage notation (e.g., 12.3%)
19
+ HEXADECIMAL = 'HEXADECIMAL', // Hex notation (e.g., 0xFF)
20
+ BINARY = 'BINARY', // Binary notation (e.g., 0b1010)
21
+ OCTAL = 'OCTAL' // Octal notation (e.g., 0o777)
22
+ }
23
+
24
+ /**
25
+ * Options for parsing numbers
26
+ */
27
+ export interface ParseOptions {
28
+ format?: NumberFormat;
29
+ base?: number;
30
+ allowFractions?: boolean;
31
+ rounding?: RoundingMode;
32
+ precision?: number;
33
+ strict?: boolean;
34
+ }
35
+
36
+ const DEFAULT_PARSE_OPTIONS: Required<ParseOptions> = {
37
+ format: NumberFormat.STANDARD,
38
+ base: 10,
39
+ allowFractions: false,
40
+ rounding: RoundingMode.HALF_EVEN,
41
+ precision: 0,
42
+ strict: true
43
+ };
44
+
45
+ /**
46
+ * Parse any supported number format to BigInt
47
+ */
48
+ export const parseNumber = (input: string, options: ParseOptions = {}): bigint => {
49
+ const opts: Required<ParseOptions> = { ...DEFAULT_PARSE_OPTIONS, ...options };
50
+
51
+ // Remove whitespace if not in strict mode
52
+ const str = opts.strict ? input : input.trim();
53
+
54
+ if (str === '') {
55
+ throw new ValidationError('Empty string cannot be parsed as a number');
56
+ }
57
+
58
+ try {
59
+ switch (opts.format) {
60
+ case NumberFormat.SCIENTIFIC:
61
+ case NumberFormat.ENGINEERING:
62
+ return parseScientificNotation(str);
63
+ case NumberFormat.COMPACT:
64
+ return parseCompactNotation(str);
65
+ case NumberFormat.FRACTION:
66
+ return parseFraction(str, opts.rounding, opts.precision);
67
+ case NumberFormat.PERCENTAGE:
68
+ return parsePercentage(str);
69
+ case NumberFormat.HEXADECIMAL:
70
+ return parseBaseNotation(str, 16);
71
+ case NumberFormat.BINARY:
72
+ return parseBaseNotation(str, 2);
73
+ case NumberFormat.OCTAL:
74
+ return parseBaseNotation(str, 8);
75
+ default:
76
+ return parseStandardNotation(str);
77
+ }
78
+ } catch (error) {
79
+ if (error instanceof ValidationError) {
80
+ throw error;
81
+ }
82
+ throw new ValidationError(`Failed to parse number: ${input}`);
83
+ }
84
+ };
85
+
86
+ /**
87
+ * Parse standard decimal notation
88
+ */
89
+ const parseStandardNotation = (str: string): bigint => {
90
+ // Remove commas and validate format
91
+ const cleanStr = str.replace(/,/g, '');
92
+ if (!/^-?\d+$/.test(cleanStr)) {
93
+ throw new ValidationError('Invalid standard notation format');
94
+ }
95
+
96
+ return BigInt(cleanStr);
97
+ };
98
+
99
+ /**
100
+ * Parse scientific notation (e.g., 1.23e4)
101
+ */
102
+ const parseScientificNotation = (str: string): bigint => {
103
+ const match = str.match(/^(-?\d*\.?\d+)e([+-]?\d+)$/i);
104
+ if (!match) {
105
+ throw new ValidationError('Invalid scientific notation format');
106
+ }
107
+
108
+ const [, coefficient, exponent] = match;
109
+ if (!coefficient) {
110
+ throw new ValidationError('Invalid scientific notation format');
111
+ }
112
+ const [intPart, fracPart = ''] = coefficient.split('.');
113
+ const normalizedCoef = intPart + fracPart;
114
+ const adjustedExp = parseInt(exponent || '0') - fracPart.length;
115
+
116
+ if (adjustedExp >= 0) {
117
+ return BigInt(normalizedCoef) * (BigInt(10) ** BigInt(adjustedExp));
118
+ } else {
119
+ return BigInt(normalizedCoef) / (BigInt(10) ** BigInt(-adjustedExp));
120
+ }
121
+ };
122
+
123
+ /**
124
+ * Parse compact notation with suffixes (e.g., 1.23M)
125
+ */
126
+ const parseCompactNotation = (str: string): bigint => {
127
+ const match = str.match(/^(-?\d*\.?\d+)\s*([KMBTQ])$/i);
128
+ if (!match) {
129
+ throw new ValidationError('Invalid compact notation format');
130
+ }
131
+
132
+ const [, number, suffix] = match;
133
+ const value = parseFloat(number || '0');
134
+
135
+ const multipliers = {
136
+ K: 1000n,
137
+ M: 1000000n,
138
+ B: 1000000000n,
139
+ T: 1000000000000n,
140
+ Q: 1000000000000000n
141
+ };
142
+
143
+ if (!suffix) {
144
+ throw new ValidationError('Invalid compact notation format');
145
+ }
146
+
147
+ const multiplier = multipliers[suffix.toUpperCase() as keyof typeof multipliers];
148
+ return BigInt(Math.round(value * Number(multiplier)));
149
+ };
150
+
151
+ /**
152
+ * Parse fraction notation (e.g., 1/3)
153
+ */
154
+ const parseFraction = (
155
+ str: string,
156
+ rounding: RoundingMode = RoundingMode.HALF_EVEN,
157
+ precision: number = 0
158
+ ): bigint => {
159
+ const [numerator, denominator] = str.split('/');
160
+ if (!numerator || !denominator) {
161
+ throw new ValidationError('Invalid fraction format');
162
+ }
163
+
164
+ const num = BigInt(numerator);
165
+ const den = BigInt(denominator);
166
+
167
+ if (den === 0n) {
168
+ throw new ValidationError('Division by zero in fraction');
169
+ }
170
+
171
+ const scale = BigInt(10) ** BigInt(precision);
172
+ const scaledResult = (num * scale) / den;
173
+
174
+ // Apply rounding if needed
175
+ if (rounding === RoundingMode.FLOOR) {
176
+ return scaledResult;
177
+ } else if (rounding === RoundingMode.CEIL) {
178
+ return scaledResult + (num * scale % den === 0n ? 0n : 1n);
179
+ }
180
+
181
+ return scaledResult;
182
+ };
183
+
184
+ /**
185
+ * Parse percentage notation (e.g., 12.3%)
186
+ */
187
+ const parsePercentage = (str: string): bigint => {
188
+ const match = str.match(/^(-?\d*\.?\d+)%$/);
189
+ if (!match) {
190
+ throw new ValidationError('Invalid percentage format');
191
+ }
192
+
193
+ const value = parseFloat(match[1] || '0');
194
+ return BigInt(Math.round(value * 100));
195
+ };
196
+
197
+ /**
198
+ * Parse number in different bases (binary, octal, hex)
199
+ */
200
+ const parseBaseNotation = (str: string, base: number): bigint => {
201
+ let cleanStr = str.toLowerCase();
202
+
203
+ // Remove prefix if present
204
+ const prefixes: Record<number, string> = {
205
+ 2: '0b',
206
+ 8: '0o',
207
+ 16: '0x'
208
+ };
209
+
210
+ const prefix = prefixes[base];
211
+ if (prefix && cleanStr.startsWith(prefix)) {
212
+ cleanStr = cleanStr.slice(2);
213
+ }
214
+
215
+ // Validate characters based on base
216
+ const validChars = {
217
+ 2: /^[01]+$/,
218
+ 8: /^[0-7]+$/,
219
+ 16: /^[0-9a-f]+$/
220
+ };
221
+
222
+ if (!validChars[base as keyof typeof validChars].test(cleanStr)) {
223
+ throw new ValidationError(`Invalid ${base}-base number format`);
224
+ }
225
+
226
+ return BigInt(`0${prefixes[base]}${cleanStr}`);
227
+ };
228
+
229
+ /**
230
+ * Detect number format from string
231
+ */
232
+ export const detectNumberFormat = (str: string): NumberFormat => {
233
+ const cleanStr = str.trim();
234
+
235
+ if (/^-?\d+$/.test(cleanStr)) return NumberFormat.STANDARD;
236
+ if (/^-?\d*\.?\d+e[+-]?\d+$/i.test(cleanStr)) return NumberFormat.SCIENTIFIC;
237
+ if (/^-?\d*\.?\d+[KMBTQ]$/i.test(cleanStr)) return NumberFormat.COMPACT;
238
+ if (/^-?\d+\/\d+$/.test(cleanStr)) return NumberFormat.FRACTION;
239
+ if (/^-?\d*\.?\d+%$/.test(cleanStr)) return NumberFormat.PERCENTAGE;
240
+ if (/^(0x|0X)[0-9a-fA-F]+$/.test(cleanStr)) return NumberFormat.HEXADECIMAL;
241
+ if (/^(0b|0B)[01]+$/.test(cleanStr)) return NumberFormat.BINARY;
242
+ if (/^(0o|0O)[0-7]+$/.test(cleanStr)) return NumberFormat.OCTAL;
243
+
244
+ throw new ValidationError('Unable to detect number format');
245
245
  };