math-engine 0.3.1__tar.gz → 0.4.0__tar.gz

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.
@@ -0,0 +1,521 @@
1
+ Metadata-Version: 2.1
2
+ Name: math-engine
3
+ Version: 0.4.0
4
+ Summary: A fast and secure mathematical expression evaluator.
5
+ Author-email: Jan Teske <jan.teske.06@gmail.com>
6
+ Project-URL: Homepage, https://github.com/JanTeske06/math_engine
7
+ Project-URL: Source, https://github.com/JanTeske06/math_engine
8
+ Project-URL: Changelog, https://github.com/JanTeske06/math_engine/blob/master/CHANGELOG.md
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+
16
+
17
+ # Math Engine 0.4.0
18
+
19
+ [![PyPI Version](https://img.shields.io/pypi/v/math-engine.svg)](https://pypi.org/project/math-engine/)
20
+ [![License: MIT](https://img.shields.io/pypi/l/math-engine.svg)](https://opensource.org/licenses/MIT)
21
+ [![Python Versions](https://img.shields.io/pypi/pyversions/math-engine.svg)](https://pypi.org/project/math-engine/)
22
+
23
+ A fast, safe, configurable expression parser and calculator for Python.
24
+
25
+ **math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
26
+ It provides a complete pipeline:
27
+
28
+ * Tokenizer
29
+ * AST (Abstract Syntax Tree) parser
30
+ * Evaluator (numeric + equation solver)
31
+ * Formatter and type-safe output system
32
+ * Support for decimal, integer, binary, octal, hexadecimal
33
+ * Custom variables
34
+ * Scientific functions
35
+ * Strict error codes for reliable debugging and automated testing
36
+
37
+ **Version 0.4.0** introduces a powerful **Command Line Interface (CLI)**
38
+
39
+ This library is ideal for:
40
+
41
+ * Developers building calculators, interpreters, scripting engines
42
+ * Students learning compilers, math parsing, and ASTs
43
+ * Security-sensitive applications where `eval()` is not acceptable
44
+ * Anyone who needs equation solving, custom formats, and strict errors
45
+
46
+ ---
47
+
48
+ # Features
49
+
50
+ ### Core Features
51
+
52
+ * Full AST-based expression parsing
53
+ * Safe evaluation (no execution of Python code)
54
+ * Decimal, Integer, Float, Boolean, Binary, Octal, Hexadecimal
55
+ * Custom variables
56
+ * Linear equation solving (`x + 3 = 7`)
57
+ * Scientific functions: `sin`, `cos`, `tan`, `log`, `sqrt`, `π`, `e^`
58
+ * Automatic format correction (`correct_output_format`)
59
+ * Strong error handling with unique codes
60
+ * Settings system with presets
61
+ * Optional strict modes:
62
+ * `only_hex`
63
+ * `only_binary`
64
+ * `only_octal`
65
+
66
+ ### Non-Decimal Support
67
+
68
+ * Read binary `0b1101`
69
+ * Read octal `0o755`
70
+ * Read hexadecimal `0xFF`
71
+ * Convert results into binary/hex/octal format
72
+ * Enforce only-hex/only-binary/only-octal mode
73
+ * Prefix parsing (`hex:`, `bin:`, `int:`, `str:` ...)
74
+
75
+ ---
76
+
77
+ # Installation
78
+
79
+ ```bash
80
+ pip install math-engine
81
+ ````
82
+
83
+ -----
84
+
85
+ # Command Line Interface (CLI)
86
+
87
+ Math Engine works directly from your terminal\! After installing via pip, you can use the command `math-engine` (or the short alias `calc`).
88
+
89
+ ### 1\. Interactive Mode (REPL)
90
+
91
+ Start the shell to calculate, manage variables, and change settings dynamically.
92
+
93
+ ```bash
94
+ $ math-engine
95
+
96
+ Math Engine 0.4.0 Interactive Shell
97
+ Type 'help' for commands, 'exit' to leave.
98
+ ----------------------------------------
99
+ Examples:
100
+ >>> 3 + 3 * 4
101
+ 15
102
+
103
+ >>> hex: 255
104
+ 0xff
105
+
106
+ >>> x + 5, x=10 (Inline Variables)
107
+ 15
108
+
109
+ >>> set setting word_size 8
110
+ Setting updated: word_size -> 8
111
+ ```
112
+
113
+ ### 2\. Direct Calculation
114
+
115
+ You can also pass expressions directly (great for scripting):
116
+
117
+ ```bash
118
+ $ math-engine "3 + 3"
119
+ 6
120
+
121
+ $ math-engine "hex: 255"
122
+ 0xff
123
+ ```
124
+
125
+ -----
126
+
127
+ # Quick Start
128
+
129
+ ## Basic Evaluation
130
+
131
+ ```python
132
+ import math_engine
133
+
134
+ math_engine.evaluate("2 + 2")
135
+ # Decimal('4')
136
+ ```
137
+
138
+ ## Different Output Formats
139
+
140
+ ```python
141
+ math_engine.evaluate("hex: 255")
142
+ # '0xff'
143
+
144
+ math_engine.evaluate("binary: 13")
145
+ # '0b1101'
146
+
147
+ math_engine.evaluate("octal: 64")
148
+ # '0o100'
149
+ ```
150
+
151
+ ## Automatic Format Correction
152
+
153
+ ```python
154
+ import math_engine
155
+
156
+ settings = math_engine.load_all_settings()
157
+ settings["correct_output_format"] = True
158
+ math_engine.load_preset(settings)
159
+
160
+ math_engine.evaluate("bool: 3+3=6")
161
+ # True
162
+ ```
163
+
164
+ ## Reset all Settings to Default
165
+
166
+ ```python
167
+ import math_engine
168
+
169
+ math_engine.reset_settings()
170
+ ```
171
+
172
+ If a requested output type does not match the actual result, `correct_output_format=True` allows math\_engine to fall back to a compatible type instead of raising an error.
173
+
174
+ -----
175
+
176
+ # Prefix System (Casting Syntax)
177
+
178
+ math\_engine supports a powerful prefix-based casting system:
179
+
180
+ | Prefix | Meaning | Example |
181
+ | -------- | ----------- | ---------------------------------- |
182
+ | `dec:` | Decimal | `dec: 3/2` → `1.50` |
183
+ | `int:` | Integer | `int: 10/3` → error if non-integer |
184
+ | `float:` | Float | `float: 1/3` |
185
+ | `bool:` | Boolean | `bool: 3 = 3` |
186
+ | `hex:` | Hexadecimal | `hex: 15` |
187
+ | `bin:` | Binary | `bin: 5` |
188
+ | `oct:` | Octal | `oct: 64` |
189
+ | `str:` | String | `str: 3+3` → `"6"` |
190
+
191
+ Example:
192
+
193
+ ```python
194
+ math_engine.evaluate("hex: 3 + 3")
195
+ # '0x6'
196
+ ```
197
+
198
+ -----
199
+
200
+ # Variables
201
+
202
+ ```python
203
+ vars = {
204
+ "A": 10,
205
+ "B": 5,
206
+ }
207
+
208
+ math_engine.evaluate("A + B", variables=vars)
209
+ # Decimal('15')
210
+ ```
211
+
212
+ Alternatively, you can pass variables as keyword arguments:
213
+
214
+ ```python
215
+ math_engine.evaluate("A + B", A=10, B=5)
216
+ # Decimal('15')
217
+ ```
218
+
219
+ Variables are mapped internally to a safe internal representation and are designed to be simple and predictable.
220
+
221
+ -----
222
+
223
+ # Scientific Functions
224
+
225
+ ```python
226
+ math_engine.evaluate("sin(30)")
227
+ math_engine.evaluate("cos(90)")
228
+ math_engine.evaluate("log(100,10)")
229
+ math_engine.evaluate("√(16)")
230
+ math_engine.evaluate("pi * 2")
231
+ ```
232
+
233
+ All functions are processed by the internal `ScientificEngine`, honoring your settings (for example, `use_degrees`).
234
+
235
+ -----
236
+
237
+ # Linear Equation Solver
238
+
239
+ ```python
240
+ math_engine.evaluate("x + 3 = 10")
241
+ # Decimal('7')
242
+ ```
243
+
244
+ Invalid or nonlinear equations produce errors with codes like:
245
+
246
+ * 3005 – Non-linear equation
247
+ * 3002 – Multiple variables
248
+ * 3022 – One side empty
249
+
250
+ -----
251
+
252
+ # Non-Decimal Numbers (Binary, Octal, Hex)
253
+
254
+ ```python
255
+ math_engine.evaluate("0xFF + 3")
256
+ # Decimal('258')
257
+
258
+ math_engine.evaluate("0b1010 * 3")
259
+ # Decimal('30')
260
+ ```
261
+
262
+ Non-decimal parsing respects the setting `allow_non_decimal`. If it is set to `False`, using `0b`, `0o`, or `0x` will raise a conversion error.
263
+
264
+ -----
265
+
266
+ # Bitwise Operations & Developer Mode (v0.4.0)
267
+
268
+ Math Engine can act as a **programmer's calculator**. It supports standard operator precedence and bitwise logic.
269
+
270
+ ### New Operators
271
+
272
+ | Operator | Description | Example | Result |
273
+ | :------- | :---------- | :------- | :----- |
274
+ | `&` | Bitwise AND | `3 & 1` | `1` |
275
+ | `\|` | Bitwise OR | `1 \| 2` | `3` |
276
+ | `^` | Bitwise XOR | `3 ^ 1` | `2` |
277
+ | `<<` | Left Shift | `1 << 2` | `4` |
278
+ | `>>` | Right Shift | `8 >> 2` | `2` |
279
+ | `**` | Power | `2 ** 3` | `8` |
280
+
281
+ > Note: Since `^` is used for **XOR**, use `**` for exponentiation (power).
282
+
283
+ ### Word Size & Overflow Simulation
284
+
285
+ You can simulate hardware constraints (like C++ `int8`, `uint16`, etc.) by setting a `word_size`.
286
+
287
+ * **`word_size: 0` (Default):** Python mode (arbitrary precision, no overflow).
288
+ * **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow) accordingly.
289
+
290
+ ### Signed vs. Unsigned Mode
291
+
292
+ When `word_size > 0`, you can control how values are interpreted via `signed_mode`:
293
+
294
+ * **`True` (Default):** Use **Two's Complement** for negative values.
295
+ * **`False`:** Treat all values as unsigned.
296
+
297
+ **Example: 8-bit Simulation**
298
+
299
+ ```python
300
+ import math_engine
301
+
302
+ settings = math_engine.load_all_settings()
303
+ settings["word_size"] = 8
304
+ settings["signed_mode"] = True
305
+ math_engine.load_preset(settings)
306
+
307
+ math_engine.evaluate("127 + 1")
308
+ # In 8-bit signed arithmetic this overflows to -128
309
+ # Decimal('-128')
310
+ ```
311
+
312
+ Hex output respects the current word size and signedness:
313
+
314
+ ```python
315
+ math_engine.evaluate("hex: -1")
316
+ # Hex representation consistent with word_size / signed_mode configuration
317
+ ```
318
+
319
+ ### Force-only-hex Mode
320
+
321
+ ```python
322
+ settings = math_engine.load_all_settings()
323
+ settings["only_hex"] = True
324
+ math_engine.load_preset(settings)
325
+
326
+ math_engine.evaluate("FF + 3")
327
+ # Decimal('258')
328
+ ```
329
+
330
+ Input validation ensures safety and prevents mixing incompatible formats in strict modes.
331
+
332
+ -----
333
+
334
+ # Settings System
335
+
336
+ You can inspect and modify settings programmatically.
337
+
338
+ ### Load Current Settings
339
+
340
+ ```python
341
+ import math_engine
342
+
343
+ settings = math_engine.load_all_settings()
344
+ print(settings)
345
+ ```
346
+
347
+ ### Apply a Full Preset
348
+
349
+ This is a plain Python `dict` (not JSON):
350
+
351
+ ```python
352
+ preset = {
353
+ "decimal_places": 2,
354
+ "use_degrees": False,
355
+ "allow_augmented_assignment": True,
356
+ "fractions": False,
357
+ "allow_non_decimal": True,
358
+ "debug": False,
359
+ "correct_output_format": True,
360
+ "default_output_format": "decimal:",
361
+ "only_hex": False,
362
+ "only_binary": False,
363
+ "only_octal": False,
364
+ # New in 0.3.0
365
+ "word_size": 0, # 0 = unlimited, or 8, 16, 32, 64
366
+ "signed_mode": True, # True = Two's Complement, False = Unsigned
367
+ }
368
+
369
+ math_engine.load_preset(preset)
370
+ ```
371
+
372
+ ### Change a Single Setting
373
+
374
+ ```python
375
+ math_engine.change_setting("decimal_places", 10)
376
+ ```
377
+
378
+ You can also read a single setting:
379
+
380
+ ```python
381
+ decimal_places = math_engine.load_one_setting("decimal_places")
382
+ ```
383
+
384
+ -----
385
+
386
+ # Error Handling
387
+
388
+ Every error is a custom exception with:
389
+
390
+ * Human-readable message
391
+ * Machine-readable error code
392
+ * Position (if applicable)
393
+ * The original expression
394
+
395
+ Example:
396
+
397
+ ```python
398
+ import math_engine
399
+ from math_engine import error as E
400
+
401
+ try:
402
+ math_engine.evaluate("1/0")
403
+ except E.CalculationError as e:
404
+ print(e.code) # 3003
405
+ print(e.message) # "Division by zero"
406
+ print(e.equation) # "1/0"
407
+ ```
408
+
409
+ ### Example Error Codes
410
+
411
+ | Code | Meaning |
412
+ | ---- | --------------------------- |
413
+ | 3003 | Division by zero |
414
+ | 3034 | Empty input |
415
+ | 3036 | Multiple = signs |
416
+ | 3032 | Multiple-character variable |
417
+ | 8000 | Conversion to int failed |
418
+ | 8006 | Output conversion error |
419
+
420
+ For a complete list of all error codes and their meanings, please see the **[Error Codes Reference](https://github.com/JanTeske06/math_engine/blob/master/ERRORS.md)**.
421
+
422
+ -----
423
+
424
+ # Testing and Reliability
425
+
426
+ math\_engine is designed with testing in mind:
427
+
428
+ * Full error-code consistency
429
+ * Strict syntax rules
430
+ * Unit-test friendly behavior
431
+ * No reliance on Python’s runtime execution
432
+
433
+ Example with `pytest`:
434
+
435
+ ```python
436
+ import pytest
437
+ import math_engine
438
+ from math_engine import error as E
439
+
440
+ def test_division_by_zero_error_code():
441
+ with pytest.raises(E.CalculationError) as exc:
442
+ math_engine.evaluate("1/0")
443
+ assert exc.value.code == "3003"
444
+ ```
445
+
446
+ You can also test more advanced behavior (non-decimal, strict modes, bitwise operations, etc.) in the same way.
447
+
448
+ -----
449
+
450
+ # Performance
451
+
452
+ * No use of Python `eval()`
453
+ * Predictable performance through AST evaluation
454
+ * Optimized tokenization
455
+ * Fast conversion of non-decimal numbers
456
+
457
+ Future updates focus on:
458
+
459
+ * Expression caching
460
+ * Compiler-like optimizations
461
+ * Faster scientific evaluation
462
+
463
+ -----
464
+
465
+ # Use Cases
466
+
467
+ ### Calculator Applications
468
+
469
+ Build full scientific or programmer calculators, both GUI and command line.
470
+
471
+ ### Education
472
+
473
+ Great for learning about lexers, parsers, ASTs, and expression evaluation.
474
+
475
+ ### Embedded Scripting
476
+
477
+ Safe math evaluation inside larger apps.
478
+
479
+ ### Security-Sensitive Input
480
+
481
+ Rejects arbitrary Python code and ensures controlled evaluation.
482
+
483
+ ### Data Processing
484
+
485
+ Conversion between hex/bin/decimal is easy and reliable.
486
+
487
+ -----
488
+
489
+ # Roadmap (Future Versions)
490
+
491
+ * Non-decimal output formatting upgrades
492
+ * Strict type-matching modes
493
+ * Function overloading
494
+ * Memory/register system
495
+ * Speed optimization via caching
496
+ * User-defined functions
497
+ * Expression pre-compilation
498
+ * Better debugging output
499
+
500
+ -----
501
+
502
+ # Changelog
503
+
504
+ See [CHANGELOG.md](https://github.com/JanTeske06/math_engine/blob/master/CHANGELOG.md) for details.
505
+
506
+ -----
507
+
508
+ # License
509
+ [MIT License](https://github.com/JanTeske06/math_engine/blob/master/LICENSE)
510
+
511
+ -----
512
+
513
+ # Contributing
514
+
515
+ Contributions are welcome.
516
+ Feel free to submit issues or PRs on GitHub:
517
+
518
+ [https://github.com/JanTeske06/math\_engine](https://github.com/JanTeske06/math_engine)
519
+
520
+ ---
521
+