daamath 0.2.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.
Files changed (52) hide show
  1. daamath-0.2.0/PKG-INFO +9 -0
  2. daamath-0.2.0/pyproject.toml +26 -0
  3. daamath-0.2.0/setup.cfg +4 -0
  4. daamath-0.2.0/src/daamath/__init__.py +23 -0
  5. daamath-0.2.0/src/daamath/aliases.py +125 -0
  6. daamath-0.2.0/src/daamath/context.py +16 -0
  7. daamath-0.2.0/src/daamath/domains.py +93 -0
  8. daamath-0.2.0/src/daamath/enums.py +11 -0
  9. daamath-0.2.0/src/daamath/exceptions.py +53 -0
  10. daamath-0.2.0/src/daamath/functions/__init__.py +27 -0
  11. daamath-0.2.0/src/daamath/functions/arithmetic.py +228 -0
  12. daamath-0.2.0/src/daamath/functions/arithmetic_extra.py +120 -0
  13. daamath-0.2.0/src/daamath/functions/combinatoric.py +15 -0
  14. daamath-0.2.0/src/daamath/functions/complex.py +16 -0
  15. daamath-0.2.0/src/daamath/functions/complex_extra.py +4 -0
  16. daamath-0.2.0/src/daamath/functions/interval.py +100 -0
  17. daamath-0.2.0/src/daamath/functions/logic.py +132 -0
  18. daamath-0.2.0/src/daamath/functions/mapping.py +239 -0
  19. daamath-0.2.0/src/daamath/functions/miscellaneous.py +196 -0
  20. daamath-0.2.0/src/daamath/functions/old_functions.py +726 -0
  21. daamath-0.2.0/src/daamath/functions/quantization.py +99 -0
  22. daamath-0.2.0/src/daamath/functions/sigmoids.py +32 -0
  23. daamath-0.2.0/src/daamath/functions/solvers.py +26 -0
  24. daamath-0.2.0/src/daamath/functions/tensor.py +70 -0
  25. daamath-0.2.0/src/daamath/functions/trigonometry.py +141 -0
  26. daamath-0.2.0/src/daamath/functions/trigonometry_extra.py +22 -0
  27. daamath-0.2.0/src/daamath/functions/variadic.py +79 -0
  28. daamath-0.2.0/src/daamath/numbers/__init__.py +21 -0
  29. daamath-0.2.0/src/daamath/numbers/constants.py +53 -0
  30. daamath-0.2.0/src/daamath/numbers/conversion_angle.py +44 -0
  31. daamath-0.2.0/src/daamath/numbers/derived.py +34 -0
  32. daamath-0.2.0/src/daamath/numbers/floating.py +14 -0
  33. daamath-0.2.0/src/daamath/strings/__init__.py +504 -0
  34. daamath-0.2.0/src/daamath/strings/arrow.py +34 -0
  35. daamath-0.2.0/src/daamath/strings/ascii.py +7 -0
  36. daamath-0.2.0/src/daamath/strings/bracket.py +103 -0
  37. daamath-0.2.0/src/daamath/strings/digit.py +17 -0
  38. daamath-0.2.0/src/daamath/strings/greek.py +31 -0
  39. daamath-0.2.0/src/daamath/strings/latin.py +38 -0
  40. daamath-0.2.0/src/daamath/strings/square.py +107 -0
  41. daamath-0.2.0/src/daamath/strings/utilities/__init__.py +2 -0
  42. daamath-0.2.0/src/daamath/strings/utilities/case.py +6 -0
  43. daamath-0.2.0/src/daamath/strings/utilities/lookup.py +37 -0
  44. daamath-0.2.0/src/daamath.egg-info/PKG-INFO +9 -0
  45. daamath-0.2.0/src/daamath.egg-info/SOURCES.txt +50 -0
  46. daamath-0.2.0/src/daamath.egg-info/dependency_links.txt +1 -0
  47. daamath-0.2.0/src/daamath.egg-info/top_level.txt +1 -0
  48. daamath-0.2.0/tests/test_comparative.py +207 -0
  49. daamath-0.2.0/tests/test_componentwise_comparative.py +240 -0
  50. daamath-0.2.0/tests/test_fact.py +22 -0
  51. daamath-0.2.0/tests/test_sumt.py +52 -0
  52. daamath-0.2.0/tests/test_trig.py +83 -0
daamath-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: daamath
3
+ Version: 0.2.0
4
+ Summary: a mathematician's spellbook: language-agnostic math library specification with implementations in various languages
5
+ Author-email: deftasparagusanaconda <deftasparagusanaconda@gmail.com>
6
+ License-Expression: GPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/deftasparagusanaconda/daamath
8
+ Requires-Python: >=3.11.0
9
+ Description-Content-Type: text/markdown
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["setuptools>=75.8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "daamath"
7
+ version = "0.2.0"
8
+ #dynamic = ["version"]
9
+ description = "a mathematician's spellbook: language-agnostic math library specification with implementations in various languages "
10
+ readme = "README.md"
11
+ requires-python = ">=3.11.0"
12
+ license = "GPL-3.0-or-later"
13
+ #package-dir = {"" = "."}
14
+ #dependencies = ["numpy", "matplotlib"]
15
+ authors = [
16
+ { name="deftasparagusanaconda", email="deftasparagusanaconda@gmail.com" }
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/deftasparagusanaconda/daamath"
21
+
22
+ [tool.setuptools]
23
+ package-dir = {"" = "src"}
24
+
25
+ [tool.setuptools.packages.find]
26
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ from .context import Context
2
+
3
+ from . import functions, numbers, strings, domains
4
+ from .functions import *
5
+ from .numbers import *
6
+ from .strings import *
7
+ from .domains import *
8
+ from . import enums
9
+
10
+ from . import aliases
11
+ from .aliases import *
12
+
13
+ from . import exceptions
14
+
15
+ context = Context(
16
+ functions = '',
17
+ datatypes = ''
18
+ # check_input_domain = True,
19
+ # check_output_domain = True,
20
+ # domain = REAL,
21
+ # error_policy = enums.ErrorPolicy.FLAG_RAISE_HALT,
22
+ # rounding = roundeven,
23
+ )
@@ -0,0 +1,125 @@
1
+ import daamath as dm
2
+
3
+ # hyperoperation
4
+ succ = dm.h0c # hyperoperation of 0th order, solving for c in the equation a ? b = c
5
+ pred = dm.h0b
6
+ add = dm.h1c
7
+ sub = dm.h1b
8
+ mul = dm.h2c
9
+ div = dm.h2b
10
+ pow = dm.h3c
11
+ log = dm.h3b
12
+ root = dm.h3a
13
+ spow = dm.h4c
14
+ slog = dm.h4b
15
+ sroot = dm.h4a
16
+
17
+ # hyperoperation extra
18
+ ainv = dm.h1b_0 # sub with first argument fixed to 0
19
+ minv = dm.h2b_1
20
+ exp = dm.h3c_e
21
+ exp2 = dm.h3c_2
22
+ exp10 = dm.h3c_10
23
+ ln = dm.h3b__e # log with second argument fixed to e
24
+ log2 = dm.h3b__2
25
+ log10 = dm.h3b__10
26
+ square = dm.h3c__2
27
+ cube = dm.h3c__3
28
+ sqrt = dm.h3a__2
29
+ cbrt = dm.h3a__3
30
+ rsquare = dm.h2b_1_h3c__2 # minv of square of x
31
+ rcube = dm.h2b_1_h3c__3
32
+ rsqrt = dm.h2b_1_h3a__2
33
+ rcbrt = dm.h2b_1_h3a__3
34
+ fma = dm.h1c_h2c # dm.add_mul
35
+ expm1 = dm.h1b_h3c_e__1 # dm.sub_pow_e__1
36
+ ln1p = dm.h3b_h1c_1__e # dm.log_add_1__e
37
+
38
+ # trigonometry
39
+ sin = dm.croh # circular ratio from opposite and hypotenuse
40
+ cos = dm.crah
41
+ tan = dm.croa
42
+ cot = dm.crao
43
+ sec = dm.crha
44
+ csc = dm.crho
45
+ asin = dm.csoh
46
+ acos = dm.csah
47
+ atan = dm.csoa
48
+ acot = dm.csao
49
+ asec = dm.csha
50
+ acsc = dm.csho
51
+ sinh = dm.hroh
52
+ cosh = dm.hrah
53
+ tanh = dm.hroa
54
+ coth = dm.hrao
55
+ sech = dm.hrha
56
+ csch = dm.hrho
57
+ asinh = dm.hsoh
58
+ acosh = dm.hsah # hyperbolic semiarea from adjacent and hypotenuse
59
+ atanh = dm.hsoa
60
+ acoth = dm.hsao
61
+ asech = dm.hsha
62
+ acsch = dm.hsho
63
+
64
+ # trigonometry extra
65
+ asin2 = dm.csoh2 # 2-argument version of dm.csoh
66
+ acos2 = dm.csah2
67
+ atan2 = dm.csoa2
68
+ acot2 = dm.csao2
69
+ asec2 = dm.csha2
70
+ acsc2 = dm.csho2
71
+ sinc = dm.h2b_croh_S_S # dm.div_sin_S_S
72
+
73
+ # boolean
74
+ not_ = dm.tf # F, T → T, F
75
+ and_ = dm.ffft # FF, FT, TF, TT → F, F, F, T
76
+ or_ = dm.fttt
77
+ xor = dm.fttf
78
+ imp = dm.ttft
79
+ con = dm.tftt
80
+ nand = dm.tttf
81
+ nor = dm.tfff
82
+ nxor = dm.tfft # NOTE: nxor, not xnor
83
+ nimp = dm.fftf
84
+ ncon = dm.ftff
85
+
86
+ # interval
87
+ lt = dm.iee # A |B| C → include exclude exclude
88
+ le = dm.iie
89
+ eq = dm.eie
90
+ ne = dm.iei
91
+ ge = dm.eii
92
+ gt = dm.eei
93
+ oo = dm.eeiee # A |B| C |D| E → exclude exclude include exclude exclude
94
+ oc = dm.eeiie
95
+ co = dm.eiiee
96
+ cc = dm.eiiie
97
+
98
+ # variadic
99
+ sum = dm.vh1c
100
+ prod = dm.vh2c
101
+ all = dm.vffft
102
+ any = dm.vfttt
103
+ min = dm.mean__h1b_0_inf
104
+ hmean = dm.mean__h1b_0_1
105
+ gmean = dm.mean__0
106
+ amean = dm.mean__1
107
+ rms = dm.mean__2
108
+ cmean = dm.mean__3
109
+ max = dm.mean__inf
110
+
111
+ # idk bro
112
+ abs = dm.norm__2
113
+ sgn = dm.normalize__2
114
+
115
+ # quantization
116
+ floor = dm.round__true_floor
117
+ ceil = dm.round__true_ceil
118
+ trunc = dm.round__true_trunc
119
+ away = dm.round__true_away
120
+ roundfloor = dm.round__false_floor
121
+ roundceil = dm.round__false_ceil
122
+ roundtrunc = dm.round__false_trunc
123
+ roundaway = dm.round__false_away
124
+ roundeven = dm.round__false_even
125
+ roundodd = dm.round__false_odd
@@ -0,0 +1,16 @@
1
+ from typing import Any
2
+ from dataclasses import dataclass
3
+
4
+ @dataclass
5
+ class Functions:
6
+ ...
7
+
8
+ @dataclass
9
+ class DataTypes:
10
+ ...
11
+
12
+ @dataclass
13
+ class Context:
14
+ "a collection of variables that define daamath's behaviour"
15
+ functions: Functions
16
+ datatypes: DataTypes
@@ -0,0 +1,93 @@
1
+ # a domain is a function with special UPPERCASE naming, because it is treated as both an object and also as a function
2
+
3
+ from typing import Any, Callable
4
+ import numbers
5
+
6
+ # 1st order domains (indicator functions):
7
+ def THING(fish: Any) -> bool:
8
+ 'the base domain of anything. everything is a thing. even nothing is a thing. the indicator function simply returns `true`'
9
+ return True
10
+
11
+ def TRUTH(fish: Any) -> bool:
12
+ 'idk'
13
+ return True
14
+
15
+ def BOOLEAN(fish: Any) -> bool:
16
+ 'idk'
17
+ return True
18
+
19
+ def NUMBER(fish: Any) -> bool:
20
+ return isinstance(fish, numbers.Number)
21
+
22
+ def HYPERCOMPLEX(fish: Any) -> bool:
23
+ 'idk'
24
+ return NUMBER(fish)
25
+
26
+ def OCTONION(fish: Any) -> bool:
27
+ 'fish is HYPERCOMPLEX and fish has non-zero octonion vector part'
28
+ return HYPERCOMPLEX(fish)
29
+
30
+ def QUATERNION(fish: Any) -> bool:
31
+ 'fish is OCTONION and fish has non-zero quaternion vector part'
32
+ return OCTONION(fish)
33
+
34
+ def COMPLEX(fish: Any) -> bool:
35
+ 'fish is QUATERNION and fish has non-zero imaginary part'
36
+ return OCTONION(fish) and fish.imag == 0
37
+
38
+ def IMAGINARY(fish: Any) -> bool:
39
+ 'fish is COMPLEX and real part is zero'
40
+ return COMPLEX(fish) and fish.real == 0
41
+
42
+ def REAL(fish: Any) -> bool:
43
+ 'fish is COMPLEX and imaginary part is zero'
44
+ return COMPLEX(fish) and fish.imag == 0
45
+
46
+ def RATIONAL(fish: Any) -> bool:
47
+ 'fish is REAL and fish can be represented as p / q where q ≠ 0'
48
+ return REAL(fish) and isinstance(fish, numbers.Rational)
49
+
50
+ def INTEGER(fish: Any) -> bool:
51
+ 'fish is RATIONAL and fish is divisible by 1'
52
+ return RATIONAL(fish) and fish % 1 == 0
53
+
54
+ def IRRATIONAL(fish: Any) -> bool:
55
+ 'fish is REAL and fish is not RATIONAL'
56
+ return REAL(fish) and not RATIONAL(fish)
57
+
58
+ def PRIME(fish: Any) -> bool:
59
+ 'fish is NATURALSTART_2 and fish has two prime divisors'
60
+ raise NotImplementedError('developer hasnt defined this yet')
61
+ return NATURALSTART
62
+
63
+ def COMPOSITE(fish: Any) -> bool:
64
+ 'fish is NATURAL_1 and fish has more than two prime divisors'
65
+ raise NotImplementedError('developer hasnt defined this yet')
66
+ return NATURALSTART_1(fish)
67
+
68
+ # 2nd order domains (domain constructors):
69
+
70
+ def NATURALFROM(start: int) -> Callable[[Any], bool]:
71
+ 'natural numbers starting from N'
72
+ if not INTEGER(start) or start < 0:
73
+ raise ValueError('start must be non-negative integer')
74
+
75
+ def NATURALFROM(fish: Any) -> bool:
76
+ return INTEGER(fish) and fish >= start
77
+ return NATURALFROM
78
+
79
+ NATURALFROM_0: Callable[[Any], bool] = NATURALFROM(0)
80
+ NATURALFROM_1: Callable[[Any], bool] = NATURALFROM(1)
81
+ NATURALFROM_2: Callable[[Any], bool] = NATURALFROM(2)
82
+
83
+ def INTEGERMODULO(mod: int) -> Callable[[Any], bool]:
84
+ 'integers modulo N, like in modular arithmetic'
85
+ if mod == 0:
86
+ return INTEGER
87
+ if not INTEGER(mod) or mod < 0:
88
+ raise ValueError(f'sorry, but i want mod to be a non-negative integer. i dont know what integers modulo {mod} would mean')
89
+ def INTEGERMODULO_N(fish: Any) -> bool:
90
+ return INTEGER(fish) and fish // mod == 0
91
+ return INTEGERMODULO
92
+
93
+ INTEGERMODULO_2: Callable[[Any], bool] = INTEGERMODULO(2)
@@ -0,0 +1,11 @@
1
+ from enum import Enum
2
+
3
+ class ErrorPolicy:
4
+ SENTINEL = 0
5
+ FLAG_SENTINEL = 1
6
+ RAISE_HALT = 2
7
+ FLAG_RAISE_HALT = 3
8
+
9
+ class SentinelPolicy:
10
+ IGNORE = 0
11
+ PROPAGATE = 1
@@ -0,0 +1,53 @@
1
+ from .context import Context
2
+ from collections.abc import Callable
3
+ from typing import Any
4
+
5
+ class Error(Exception):
6
+ 'the base class of any exception in daamath'
7
+
8
+ class DomainError(Error, ArithmeticError):
9
+ 'this occurs when something related to the domain goes wrong'
10
+
11
+ class DataTypeError(Error, TypeError):
12
+ 'this occurs when something related to the datatype goes wrong'
13
+
14
+ class OutOfDomainError(DomainError):
15
+ 'this occurs when something is unexpectedly not in a domain'
16
+
17
+ def __init__(self, function_or_str: Callable | str, args: tuple[...] = None, kwargs: dict[str, Any] = None, output: Any = None, context: Context = None):
18
+ 'the arguments here are entirely optional. these are just here to help you format the error message neater'
19
+ if args is None and kwargs is None and output is None:
20
+ super().__init__(function_or_str)
21
+ return
22
+
23
+ if args is None or kwargs is None or output is None:
24
+ raise ValueError('developer! lazy developer! give args, kwargs, output for this function')
25
+
26
+ raise NotImplementedError
27
+
28
+ args: str = ', '.join(f'{type(input).__name__} {input}' for arg in args)
29
+ kwargs: str = ', '.join(f'{key}={val!r}' for key, val in kwargs)
30
+
31
+ function: str = function_or_str.__name__
32
+ inputs: list[Any] = [f'{type(input).__name__} {input}' for arg in args] + []
33
+ input_types: list[Any] = [f'{type(input).__name__} {input}' for arg in args] + []
34
+ input_domains: list[Any] = []
35
+ output_type: str = type(output).__name__
36
+ output_domain: str = str(getattr(context.functions, function.__name__))
37
+
38
+ super().__init__(f'{function}{output_type} {output} which is not {output_domain}')
39
+
40
+ # this cheeky hack allows it to show things like:
41
+ # ClosureError: float INTEGER div(float INTEGER 1.0, float INTEGER 2.0) returned float 0.5 which is not INTEGER
42
+ # instead of:
43
+ # dm.exceptions.ClosureError: float INTEGER div(float INTEGER 1.0, float INTEGER 2.0) returned float 0.5 which is not INTEGER
44
+ __module__ = 'builtins'
45
+
46
+ class FidelityError(DataTypeError):
47
+ 'this occurs when a datatype cannot represent something accurately'
48
+
49
+ # this cheeky hack allows it to show things like:
50
+ # RepresentationError: int REAL div(int REAL 1.0, int REAL 2.0) returned REAL 0.5 which cannot be accurately represented by int
51
+ # instead of:
52
+ # dm.exceptions.RepresentationError: int REAL div(int REAL 1.0, int REAL 2.0) returned REAL 0.5 which cannot be accurately represented by int
53
+ __module__ = 'builtins'
@@ -0,0 +1,27 @@
1
+ # hey! you! yeah, you! daa!
2
+ #
3
+ # also, implement vector products like dot product, cross product (just a compositon of wedge product and hodge star. also, in 3D and 7D only! because they tie with quaternions and octonions, but none higher. no more normed algebrae after that), wedge product,
4
+
5
+ from . import arithmetic, arithmetic_extra, complex, complex_extra, trigonometry, trigonometry_extra, logic, interval, combinatoric, variadic, quantization, sigmoids, mapping, tensor, miscellaneous
6
+
7
+ from .arithmetic import h0c, h0b, h1c, h1b, h2c, h2b, h3c, h3b, h3a, h4c, h4b, h4a
8
+ from .arithmetic_extra import h1b_0, h2b_1, h3c_e, h3c_2, h3c_10, h3b__e, h3b__2, h3b__10, h3c__2, h3c__3, h3a__2, h3a__3, h2b_1_h3c__2, h2b_1_h3c__3, h2b_1_h3a__2, h2b_1_h3a__3, h1c_h2c, h1b_h3c_e__1, h3b_h1c_1__e
9
+
10
+ from .complex import real, imag, arg, rect, polar, conj
11
+ from .complex_extra import cis
12
+
13
+ from .trigonometry import croh, crah, croa, crao, crha, crho, csoh, csah, csoa, csao, csha, csho, hroh, hrah, hroa, hrao, hrha, hrho, hsoh, hsah, hsoa, hsao, hsha, hsho
14
+ from .trigonometry_extra import csoh2, csah2, csoa2, csao2, csha2, csho2, h2b_croh_S_S
15
+
16
+ from .logic import tf, ffft, fttt, fttf, ttft, tftt, tttf, tfff, tfft, fftf, ftff
17
+ from .interval import iee, iie, eie, iei, eii, eei, eeiee, eeiie, eiiee, eiiie
18
+
19
+ from .variadic import vffft, vfttt, vh1c, vh2c, mean, mean__h1b_0_inf, mean__h1b_0_1, mean__0, mean__1, mean__2, mean__3, mean__inf, vparallel
20
+ from .combinatoric import fact, sumt, comb, perm, gcd, lcm
21
+ from .quantization import round, round__true_floor, round__true_ceil, round__true_trunc, round__true_away, round__false_floor, round__false_ceil, round__false_trunc, round__false_away, round__false_even, round__false_odd, quot, rem, quotrem
22
+ from .sigmoids import sigmoid_tan, sigmoid_tanh
23
+ from .mapping import lerp, unlerp, map, fixed_log, fixed_exp, soft_log, soft_exp
24
+ from .tensor import norm, normalize, clamp, norm__2, normalize__2
25
+ from .miscellaneous import ifelse
26
+
27
+ from .solvers import roots, coeffs
@@ -0,0 +1,228 @@
1
+ # these operators dont treat nested lists as tensors. do you know why?
2
+ # because the tensor object should know itself how to do basic math ops. an operator is an operator.. an object should know what to do with an operator.
3
+ # its also because this tensor mechanism is hard to scale across languages
4
+
5
+ '''
6
+ instead of:
7
+ root sroot
8
+ | |
9
+ pow -- spow -- …
10
+ /
11
+ succ -- add -- mul
12
+ | | | \
13
+ pred sub div exp -- sexp -- …
14
+ | |
15
+ log slog
16
+
17
+ we should have:
18
+ X h0X h1X h2X h3X h4X h5X …
19
+ c ++b a + b a * b a ^ b a ↑ b a ⇑ b …
20
+ b --c c - a c / a c L b … … …
21
+ a N/A c - b c / b c √ b … … …
22
+
23
+ where we X is the variable we solve for in the equation a ? b = c
24
+ '''
25
+
26
+ # NOTE: i expect these function signatures:
27
+ # hXc(a, b)
28
+ # hXb(c, a)
29
+ # hXa(c, b)
30
+ #
31
+ # i could make it a cycle of variables like so:
32
+ # hXc(a, b)
33
+ # hXb(c, a)
34
+ # hXa(b, c)
35
+ #
36
+ # but this would imply that the three variables are involved in a cyclic relation a → b → c → a when, really, they are involved in a 2 → 1 relation a, b → c. thats why when solving for b and a, we make it intentionally asymmetric
37
+
38
+ import math, cmath, functools
39
+ from numbers import Number, Real, Integral
40
+ from typing import Literal
41
+ from ..exceptions import DomainError
42
+
43
+
44
+ #h0c = functools.partial(h1c, a = 1)
45
+ def h0c(b: Integral) -> Integral:
46
+ 'c = ++b, successor. the 0th hyperoperation'
47
+ if not isinstance(b, Integral):
48
+ raise DomainError('')
49
+ c = b + 1
50
+
51
+ if type(c) != type(b):
52
+ raise DomainError(succ, (b, ), c)
53
+
54
+ return c
55
+
56
+ #h0b = functools.partial(h1b, x = 1)
57
+ def h0b(c):
58
+ 'b = --c, predecessor. the inverse of the 0th hyperoperation'
59
+ b = c - 1
60
+
61
+ if type(b) != type(c):
62
+ raise DomainError(pred, (c, ), b)
63
+
64
+ return b
65
+
66
+ def h1c(a, b):
67
+ 'c = a + b, addition. the 1st hyperoperation'
68
+ if type(a) != type(b):
69
+ raise TypeError(f'{a} and {b} must be same type')
70
+
71
+ c = a + b
72
+
73
+ if type(a) != type(c):
74
+ raise DomainError(add, (a, b), c)
75
+
76
+ return c
77
+
78
+ def h1b(c, a):
79
+ 'b = c - a, left subtraction. the inverse of the 1st hyperoperation'
80
+ if type(c) != type(a):
81
+ raise TypeError(f'{c} and {a} must be same type')
82
+
83
+ b = c - a
84
+
85
+ if type(b) != type(c):
86
+ raise DomainError(sub, (c, a), b)
87
+
88
+ return b
89
+
90
+ def h2c(a, b):
91
+ 'c = a * b, multiplication. the 2nd hyperoperation'
92
+ if type(a) != type(b):
93
+ raise TypeError(f'{a} and {b} must be same type')
94
+
95
+ c = a * b
96
+
97
+ if type(c) != type(a):
98
+ raise DomainError(mul, (a, b), c)
99
+
100
+ return c
101
+
102
+ def h2b(c, a):
103
+ 'b = c / a, left division. the inverse of the 2nd hyperoperation'
104
+ if type(c) != type(a):
105
+ raise TypeError(f'{c} and {a} must be same type')
106
+
107
+ if isinstance(a, int) and a % b != 0:
108
+ raise DomainError
109
+ b = c / a
110
+
111
+ if type(b) != type(c):
112
+ raise DomainError(div, (c, a), b)
113
+
114
+ return b
115
+
116
+ def h3c(a, b):
117
+ 'c = a ^ b, power, exponentiation. the 3rd hyperoperation'
118
+ if type(a) != type(b):
119
+ raise TypeError(f'{a} and {b} must be same type')
120
+
121
+ c = a ** b
122
+
123
+ if type(c) != type(a):
124
+ raise DomainError(pow, (a, b), c)
125
+
126
+ return c
127
+
128
+ def h3b(a, c):
129
+ 'b = log_a(c), logarithm. the inverse of the 3rd hyperoperation that solves for b'
130
+ # c = a ^ b
131
+ if type(a) != type(c):
132
+ raise TypeError(f'{a} and {c} must be same type')
133
+
134
+ try:
135
+ b = math.log(c, a)
136
+ except:
137
+ b = cmath.log(c, a)
138
+
139
+ if type(b) != type(a):
140
+ raise DomainError(log, (a, c), b)
141
+
142
+ return b
143
+
144
+ def h3a(b, c):
145
+ 'a = b √ c, n-th root. the inverse of the 3rd hyperoperation that solves for a'
146
+ if type(b) != type(c):
147
+ raise TypeError(f'{b} and {c} must be same type')
148
+ # c = a ^ b
149
+ a = c ** (1 / b)
150
+
151
+ if type(a) != type(b):
152
+ raise DomainError(root, (b, c), a)
153
+
154
+ return a
155
+
156
+ def h4c(a, b):
157
+ 'c = a ↑ b, tetration, superexponentiation, the 4th hyperoperation'
158
+ if type(a) != type(b):
159
+ raise TypeError(f'{a} and {b} must be same type')
160
+
161
+ raise NotImplementedError
162
+
163
+ if type(c) != type(a):
164
+ raise DomainError(spow, (a, b), c)
165
+
166
+ return c
167
+
168
+ def h4b(a, c):
169
+ 'b = slog_a(c), superlogarithm, the inverse of the 4th hyperoperation'
170
+ if type(a) != type(c):
171
+ raise TypeError(f'{a} and {c} must be same type')
172
+
173
+ raise NotImplementedError
174
+
175
+ if type(b) != type(a):
176
+ raise DomainError(slog, (a, c), b)
177
+
178
+ return b
179
+
180
+ def h4a(b, c):
181
+ 'superroot. idfk what this is supposed to be in terms of code'
182
+ if type(b) != type(c):
183
+ raise TypeError(f'{b} and {c} must be same type')
184
+
185
+ raise NotImplementedError
186
+
187
+ if type(b) != type(a):
188
+ raise DomainError(slog, (b, c), a)
189
+
190
+ return a
191
+
192
+
193
+ '''
194
+ # this thing is just a novelty
195
+ def hyper(
196
+ left: Number,
197
+ right: Number,
198
+ n: int,
199
+ solve: Literal['a', 'b', 'c'] = 'c',
200
+ ) -> Number:
201
+ match solve:
202
+ case 'a':
203
+ match n:
204
+ case 0: raise ArithmeticError('this operation simply does not exist in mathematics')
205
+ case 1: return h1a(left, right)
206
+ case 2: return h2a(left, right)
207
+ case 3: return h3a(left, right)
208
+ case 4: return h4a(left, right)
209
+ case _: raise NotImplementedError
210
+ case 'b':
211
+ match n:
212
+ case 0: return h0b(right)
213
+ case 1: return h1b(left, right)
214
+ case 2: return h2b(left, right)
215
+ case 3: return h3b(left, right)
216
+ case 4: return h4b(left, right)
217
+ case _: raise NotImplementedError
218
+ case 'c':
219
+ match n:
220
+ case 0: return h0c(right)
221
+ case 1: return h1c(left, right)
222
+ case 2: return h2c(left, right)
223
+ case 3: return h3c(left, right)
224
+ case 4: return h4c(left, right)
225
+ case _: raise NotImplementedError
226
+ case _:
227
+ raise ValueError("invalid solve parameter. must be one of {'a', 'b', 'c'}")
228
+ '''