AxiomX 0.1.2__tar.gz → 0.1.4__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,20 @@
1
+ import time
2
+
3
+ """
4
+ AxiomX 0.1.4, the pure Python Scientific Math Library.
5
+
6
+ We have updated a lot and have improved accuracy. Trig Functions are calculated using CORDIC. Also we have updated our graphing system, with zooming, panning and gridlines. If you have any suggestions, email us at axiomx.python@gmail.com. Thank you all for acknowledging AxiomX.
7
+ """
8
+
9
+ print("AxiomX loading...")
10
+ time.sleep(3)
11
+ print("AxiomX is ready to use!")
12
+
13
+ import AxiomX.constants
14
+ import AxiomX.calculus
15
+ import AxiomX.functions
16
+ import AxiomX.exp
17
+ import AxiomX.trig
18
+ import AxiomX.hyperbolic
19
+
20
+ version = '0.1.0'
@@ -1,5 +1,13 @@
1
+ """
2
+ AxiomX.calculus - the calculus module of AxiomX.
3
+
4
+ AxiomX.calculus helps in doing advanced calculus like evaluating integrals, summations and also does convergence analysis.
5
+ """
6
+
7
+
1
8
  # integrating integrals
2
9
  def integrate(function, lowlim, uplim, n=10000):
10
+ """Integrates functions with the help of Simpson's Rule."""
3
11
  h = (uplim - lowlim) / n
4
12
  s = function(lowlim) + function(uplim)
5
13
 
@@ -13,6 +21,7 @@ def integrate(function, lowlim, uplim, n=10000):
13
21
  return s * h / 3
14
22
 
15
23
  def summation(lowlim, uplim, function, max_terms=10**6):
24
+ """Sums up a function from a given lower limit to an upper limit (also supports infinity)."""
16
25
  total = 0
17
26
  count = 0
18
27
 
@@ -42,6 +51,7 @@ def summation(lowlim, uplim, function, max_terms=10**6):
42
51
  return total
43
52
 
44
53
  def converges(f, tolerance=1e-6, max_terms=10**6):
54
+ """Check if a given function converges or diverges."""
45
55
  total = 0
46
56
  prev = 0
47
57
 
@@ -57,39 +67,4 @@ def converges(f, tolerance=1e-6, max_terms=10**6):
57
67
 
58
68
  prev = total
59
69
 
60
- return False
61
-
62
- def lim(f, xlim, tol=1e-5):
63
- # Try direct substitution
64
- try:
65
- return f(xlim)
66
- except ZeroDivisionError:
67
- pass # expected for limits
68
- except Exception as e:
69
- return None # or raise e if you want strict behavior
70
-
71
- hs = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5]
72
- left_vals = []
73
- right_vals = []
74
-
75
- for h in hs:
76
- try:
77
- left_vals.append(f(xlim - h))
78
- except ZeroDivisionError:
79
- continue
80
-
81
- try:
82
- right_vals.append(f(xlim + h))
83
- except ZeroDivisionError:
84
- continue
85
-
86
- if not left_vals or not right_vals:
87
- return None
88
-
89
- left = left_vals[-1]
90
- right = right_vals[-1]
91
-
92
- if abs(left - right) < tol:
93
- return (left + right) / 2
94
-
95
- return None
70
+ return False
@@ -0,0 +1,69 @@
1
+ """
2
+ AxiomX.constants - the constants module of AxiomX.
3
+
4
+ AxiomX provides a large variety of constants, unlike the default math library which contains only pi, e and tau. Our library also contains series of constants like Bernoulli numbers, Stieltjes Numbers, Harmonic numbers, etc.
5
+ """
6
+
7
+ from AxiomX.calculus import *
8
+ from AxiomX.functions import *
9
+ from AxiomX.exp import *
10
+
11
+ pi = 3.141592653589793
12
+ e = 2.718281828459045
13
+ tau = 2*pi
14
+ lemniscate = 2.622057554292119
15
+ gauss = lemniscate / pi
16
+ euler_mascheroni = 0.577215664901533
17
+ sqrt_2 = 2**0.5
18
+ sqrt_3 = 3**0.5
19
+ sqrt_5 = 5**0.5
20
+ golden_ratio = (1 + sqrt_5) / 2
21
+ silver_ratio = 1 + sqrt_2
22
+ gelfond = e**pi
23
+ gelfond_schneider = 2**sqrt_2
24
+ infinity = float("inf")
25
+
26
+ def metallic_ratio(n):
27
+ """Returns the metallic ratio of order n."""
28
+ return (n + (n**2 + 4)**0.5) / 2
29
+
30
+ def harmonic_number(n):
31
+ """Returns the nth Harmonic number."""
32
+ return summation(1, n, lambda x:1/x)
33
+
34
+ def bernoulli(n):
35
+ """Returns the nth Bernoulli number."""
36
+ B = [0] * (n + 1)
37
+ B[0] = 1
38
+
39
+ for m in range(1, n + 1):
40
+ B[m] = 0
41
+ for k in range(m):
42
+ B[m] -= (bc(m + 1, k) * B[k])
43
+ B[m] /= (m + 1)
44
+
45
+ if n % 2 == 1:
46
+ if n == 1:
47
+ return 0.5
48
+ return 0.0
49
+ return B[n]
50
+
51
+ from decimal import Decimal, getcontext
52
+
53
+ def stieltjes(m, N=200000):
54
+ """Returns the mth Stieltjes number."""
55
+ if m==0:
56
+ return euler_mascheroni
57
+ getcontext().prec = 40 # extra precision buffer
58
+
59
+ s = Decimal(0)
60
+
61
+ for k in range(1, N+1):
62
+ kD = Decimal(k)
63
+ ln = kD.ln()
64
+ s += (ln**m) / kD
65
+
66
+ Nln = Decimal(N).ln()
67
+ correction = (Nln**(m+1)) / Decimal(m+1)
68
+
69
+ return float(+ (s - correction)) # unary + applies rounding
@@ -1,7 +1,17 @@
1
+ """
2
+ AxiomX.exp - the Exponential and Logarithmic functions module of AxiomX.
3
+
4
+ The AxiomX.exp module contains exponential and logarithmic functions.
5
+ """
6
+
7
+ from AxiomX.constants import *
8
+
1
9
  def exp(n):
10
+ """Returns e**n, where e = 2.718281828459045."""
2
11
  return e**n
3
12
 
4
13
  def ln(x):
14
+ """Return the the natural logarithm of x."""
5
15
  if x <= 0:
6
16
  raise ValueError("ln(x) is undefined for x <= 0")
7
17
  k = 0
@@ -23,10 +33,13 @@ def ln(x):
23
33
  return 2*s + k * (0.693147180559945309417232121458176568) # ln 2
24
34
 
25
35
  def log10(x):
36
+ """Returns the common logarithm of x."""
26
37
  return ln(x) / ln(10)
27
38
 
28
39
  def log2(x):
40
+ """Returns the binary logarithm of x."""
29
41
  return log10(x) / log10(2)
30
42
 
31
- def log(arg, base):
32
- return log2(arg) / log2(base)
43
+ def log(x, b):
44
+ """Returns the logarithm of x to the base b."""
45
+ return log2(x) / log2(b)
@@ -1,10 +1,17 @@
1
+ from AxiomX.constants import *
2
+
3
+ """
4
+ AxiomX.functions - the Arithmetic functions module of AxiomX.
5
+
6
+ This module contains arithmetic functions like square root, absolute value, cube root, Gamma function, etc.
7
+ """
8
+
1
9
  def absolute(x):
2
- if (x > 0):
3
- return x
4
- else:
5
- return -x
10
+ """Returns the absolute value of x."""
11
+ return x if x >= 0 else -x
6
12
 
7
13
  def sqrt(a, x0=None, tol=1e-30, max_iter=20):
14
+ """Returns the square root of a by Halley's Method."""
8
15
  if a < 0:
9
16
  raise ValueError("a must be non-negative")
10
17
 
@@ -27,6 +34,7 @@ def sqrt(a, x0=None, tol=1e-30, max_iter=20):
27
34
 
28
35
 
29
36
  def cbrt(N, tolerance=1e-10, max_iterations=1000):
37
+ """Returns the cube root of N by Newton-Raphson method."""
30
38
  x = N / 3.0 if N != 0 else 0.0
31
39
  for i in range(max_iterations):
32
40
  x_next = x - (x**3 - N) / (3 * x**2)
@@ -36,6 +44,7 @@ def cbrt(N, tolerance=1e-10, max_iterations=1000):
36
44
  return x
37
45
 
38
46
  def gamma(x):
47
+ """Returns the Gamma function evaluated at x."""
39
48
  # Lanczos approximation constants
40
49
  p = [
41
50
  0.99999999999980993,
@@ -62,8 +71,9 @@ def gamma(x):
62
71
  return sqrt(2 * pi) * (x + g + 0.5)**(x + 0.5) * (e**(-(x + g + 0.5))) * t
63
72
 
64
73
  def factorial(x):
74
+ """Calculates the factorial of x with the help of Gamma function."""
65
75
  if (x // 1 == x):
66
- f = 1
76
+ f = 1.0
67
77
  while x > 0:
68
78
  f *= x
69
79
  x -= 1
@@ -72,22 +82,25 @@ def factorial(x):
72
82
  return gamma(x+1)
73
83
 
74
84
  def zeta(n):
85
+ """Returns the value of the Riemann Zeta Function evaluated at n."""
75
86
  zetval = 0
76
87
  if n <= 1:
77
88
  raise ValueError("zeta(n) diverges for n <= 1")
78
- for _ in range(1, 100001):
89
+ for _ in range(1, 1000001):
79
90
  zetval += (1 / _**n)
80
91
  return zetval
81
92
 
82
93
  def beta(n):
94
+ """Returns the value of the Dirichlet Beta function evaluated at n."""
83
95
  if n == 0:
84
96
  return 0.5
85
97
  total = 0.0
86
- for i in range(100000):
98
+ for i in range(1000000):
87
99
  total += ((-1)**i) / ((2*i + 1)**n)
88
100
  return total
89
101
 
90
102
  def bc(n, k):
103
+ """Returns the number of n things taken r at a time."""
91
104
  if k < 0 or k > n:
92
105
  raise ValueError("Binomial coefficient (n k) doesn't work for negative n or k, or if n < k")
93
106
 
@@ -100,6 +113,7 @@ def bc(n, k):
100
113
  return result
101
114
 
102
115
  def pascal(row):
116
+ """Returns a list containing all numbers on that row of the Pascal's Triangle."""
103
117
  pr = []
104
118
  for i in range(0, row+1):
105
119
  pr.append(int(bc(row, i)))
@@ -0,0 +1,332 @@
1
+ """
2
+ AxiomX.graph - the graphing module of AxiomX.
3
+
4
+ This module provides interactive 2D plotting using turtle graphics.
5
+
6
+ Features
7
+ --------
8
+ - Multiple function plotting
9
+ - Zoom and pan controls
10
+ - Dynamic grid and axis rendering
11
+ - Real-time mouse coordinate tracking
12
+
13
+ Controls
14
+ --------
15
+ Keyboard:
16
+ PageUp → Zoom in
17
+ PageDown → Zoom out
18
+ Arrow keys → Pan (← ↑ → ↓)
19
+
20
+ Mouse:
21
+ Move cursor to see real-time coordinates
22
+
23
+ Buttons:
24
+ Zoom In / Zoom Out / Arrow buttons available at bottom
25
+
26
+ Example
27
+ -------
28
+ >>> import AxiomX.graph import plot
29
+ >>> plot(lambda x: x**2, -10, 10)
30
+ """
31
+
32
+ import tkinter as tk
33
+ import turtle
34
+
35
+ def plot(funcs, start, end, step=0.1, scale=20, limit=1000):
36
+ """
37
+ Plot one or more mathematical functions on an interactive graph.
38
+
39
+ Parameters
40
+ ----------
41
+ funcs : callable or list of callables
42
+ A function f(x) or list of functions to plot.
43
+ Example: lambda x: x**2
44
+ start : float
45
+ Starting value of x-axis.
46
+ end : float
47
+ Ending value of x-axis.
48
+ step : float, optional
49
+ Step size for plotting points (default is 0.1).
50
+ scale : float, optional
51
+ Zoom level of the graph (default is 20).
52
+ limit : float, optional
53
+ Maximum absolute y-value before skipping (prevents overflow).
54
+
55
+ Returns
56
+ -------
57
+ None
58
+
59
+ Features
60
+ --------
61
+ - Supports multiple functions with different colors
62
+ - Infinite-style grid with dynamic tick spacing
63
+ - Zoom and pan using keyboard or buttons
64
+ - Displays real-time mouse coordinates
65
+
66
+ Controls
67
+ --------
68
+ PageUp / PageDown : Zoom in / out
69
+ Arrow Keys : Pan graph
70
+ Mouse Move : Show coordinates
71
+
72
+ Examples
73
+ --------
74
+ >>> plot(lambda x: x**2, -10, 10)
75
+
76
+ >>> plot([lambda x: x, lambda x: x**2], -5, 5)
77
+
78
+ Notes
79
+ -----
80
+ - Discontinuous functions (like tan(x)) are handled by skipping large jumps.
81
+ - Functions returning None or extremely large values are ignored.
82
+ - Uses turtle graphics internally, so performance may vary for small step sizes.
83
+ """
84
+ if not isinstance(funcs, list):
85
+ funcs = [funcs]
86
+
87
+ turtle.hideturtle()
88
+
89
+ try:
90
+ turtle.reset()
91
+ except turtle.Terminator:
92
+ turtle.Screen()
93
+
94
+ screen = turtle.Screen()
95
+ root = screen._root # access tk window
96
+ root.geometry("800x600")
97
+ root.resizable(False, False)
98
+ turtle.hideturtle()
99
+ screen.title("AxiomX Graph")
100
+ screen.listen()
101
+
102
+ t = turtle.Turtle(visible=False)
103
+ t.speed(0)
104
+ t.hideturtle()
105
+
106
+ turtle.tracer(0, 0)
107
+
108
+ state = {"scale": scale,"offset_x": 0,"offset_y": 0}
109
+
110
+ def draw():
111
+ t.clear()
112
+ scale = state["scale"]
113
+ t.color("lightgray")
114
+ xrange = int(400 / state['scale'])
115
+
116
+ x_start = int(-xrange - state["offset_x"])
117
+ x_end = int(xrange - state["offset_x"])
118
+
119
+ for x in range(x_start, x_end):
120
+ sx = (x + state["offset_x"]) * state["scale"]
121
+ t.penup()
122
+ t.goto(sx, -300)
123
+ t.pendown()
124
+ t.goto(sx, 300)
125
+
126
+ y_range = int(300 / state["scale"])
127
+ for y in range(-y_range, y_range+1):
128
+ sy = (y + state["offset_y"]) * state["scale"]
129
+ t.penup()
130
+ t.goto(-400, sy)
131
+ t.pendown()
132
+ t.goto(400, sy)
133
+
134
+
135
+ t.color("black")
136
+
137
+ # ================= AXES =================
138
+ # X-axis (y = 0)
139
+ t.penup()
140
+ t.goto(-400, (0 + state["offset_y"]) * state["scale"])
141
+ t.pendown()
142
+ t.goto(400, (0 + state["offset_y"]) * state["scale"])
143
+
144
+ # Y-axis (x = 0)
145
+ t.penup()
146
+ t.goto((0 + state["offset_x"]) * state["scale"], -300)
147
+ t.pendown()
148
+ t.goto((0 + state["offset_x"]) * state["scale"], 300)
149
+
150
+ # ================= X TICKS =================
151
+ # ================= X-AXIS TICKS (INFINITE STYLE) =================
152
+
153
+ t.color("black")
154
+
155
+ x_range = 400 / state["scale"]
156
+
157
+ # dynamic tick spacing (prevents clutter)
158
+ tick_step = max(1, int((2 * x_range) / 10))
159
+
160
+ # start from left visible edge
161
+ x_tick = int((-x_range - state["offset_x"]) // tick_step) * tick_step
162
+
163
+ while x_tick <= (x_range - state["offset_x"]):
164
+ sx = (x_tick + state["offset_x"]) * state["scale"]
165
+
166
+ # Tick mark
167
+ t.penup()
168
+ t.goto(sx, state["offset_y"] * state["scale"] - 5)
169
+ t.pendown()
170
+ t.goto(sx, state["offset_y"] * state["scale"] + 5)
171
+
172
+ # Label
173
+ t.penup()
174
+ t.goto(sx, state["offset_y"] * state["scale"] - 20)
175
+
176
+ label = "0" if abs(x_tick) < 1e-9 else str(x_tick)
177
+ t.write(label, align="center", font=("Arial", 8, "normal"))
178
+
179
+ x_tick += tick_step
180
+
181
+ # ================= Y TICKS =================
182
+
183
+ t.color("black")
184
+
185
+ y_range = 300 / state["scale"]
186
+
187
+ # dynamic spacing
188
+ y_tick_step = max(1, int((2 * y_range) / 10))
189
+
190
+ # start from bottom visible region (WITH offset)
191
+ y_tick = int((-y_range - state["offset_y"]) // y_tick_step) * y_tick_step
192
+
193
+ y_end = (y_range - state["offset_y"])
194
+
195
+ while y_tick <= y_end:
196
+ sy = (y_tick + state["offset_y"]) * state["scale"]
197
+
198
+ if abs(y_tick) < 1e-9:
199
+ y_tick += y_tick_step
200
+ continue
201
+
202
+ # Tick mark
203
+ t.penup()
204
+ t.goto((state["offset_x"]) * state["scale"] - 5, sy)
205
+ t.pendown()
206
+ t.goto((state["offset_x"]) * state["scale"] + 5, sy)
207
+
208
+ # Label
209
+ t.penup()
210
+ t.goto((state["offset_x"]) * state["scale"] - 10, sy - 5)
211
+ t.write(f"{y_tick}", align="right", font=("Arial", 8, "normal"))
212
+
213
+ y_tick += y_tick_step
214
+ # ================= FUNCTIONS =================
215
+ colors = ["red", "blue", "green", "purple"]
216
+
217
+ for i, f in enumerate(funcs):
218
+ t.color(colors[i % len(colors)])
219
+ t.penup()
220
+
221
+ x = start
222
+ drawing = False
223
+
224
+ while x <= end:
225
+ try:
226
+ y = f(x)
227
+
228
+ if y is None or abs(y) > limit:
229
+ raise ValueError
230
+
231
+ sx = (x + state["offset_x"]) * state["scale"]
232
+ sy = (y + state["offset_y"]) * state["scale"]
233
+
234
+ if not drawing:
235
+ t.goto(sx, sy)
236
+ t.pendown()
237
+ drawing = True
238
+ else:
239
+ t.goto(sx, sy)
240
+
241
+ except:
242
+ t.penup()
243
+ drawing = False
244
+
245
+ x += step
246
+
247
+ turtle.update()
248
+
249
+ # ================= ZOOM =================
250
+ def zoom_in():
251
+ state["scale"] *= 1.2
252
+ draw()
253
+
254
+ def zoom_out():
255
+ state["scale"] /= 1.2
256
+ draw()
257
+
258
+ def pan_left():
259
+ state["offset_x"] += 1
260
+ draw()
261
+
262
+ def pan_right():
263
+ state["offset_x"] -= 1
264
+ draw()
265
+
266
+ def pan_up():
267
+ state["offset_y"] -= 1
268
+ draw()
269
+
270
+ def pan_down():
271
+ state["offset_y"] += 1
272
+ draw()
273
+
274
+ # ================= MOUSE COORDINATES =================
275
+
276
+ canvas = screen.getcanvas()
277
+
278
+ coord_t = turtle.Turtle(visible=False)
279
+ coord_t.penup()
280
+ coord_t.color("black")
281
+
282
+ def on_mouse_move(event):
283
+ # Get canvas size
284
+ width = canvas.winfo_width()
285
+ height = canvas.winfo_height()
286
+
287
+ # Convert screen pixels → turtle coordinates
288
+ x_screen = event.x - width / 2
289
+ y_screen = height / 2 - event.y
290
+
291
+ # Convert → graph coordinates (VERY IMPORTANT)
292
+ x_graph = x_screen / state["scale"] - state["offset_x"]
293
+ y_graph = y_screen / state["scale"] - state["offset_y"]
294
+
295
+ show_coords(x_graph, y_graph)
296
+
297
+ def show_coords(x, y):
298
+ coord_t.clear()
299
+
300
+ # Display position (top-left corner)
301
+ coord_t.goto(-380, 260)
302
+
303
+ # Round for clean display
304
+ text = f"x = {x:.3f}, y = {y:.3f}"
305
+
306
+ coord_t.write(text, font=("Arial", 10, "normal"))
307
+
308
+ # Bind mouse movement
309
+ canvas.bind("<Motion>", on_mouse_move)
310
+
311
+ # Bind keys
312
+ screen.listen()
313
+ screen.onkey(zoom_in, "Next")
314
+ screen.onkey(zoom_out, "Prior")
315
+ screen.onkey(pan_right, "Right")
316
+ screen.onkey(pan_left, "Left")
317
+ screen.onkey(pan_up, "Up")
318
+ screen.onkey(pan_down, "Down")
319
+
320
+ root = screen._root
321
+
322
+ draw()
323
+ frame = tk.Frame(root)
324
+ frame.pack(side="bottom")
325
+
326
+ tk.Button(frame, text="Zoom In", command=zoom_in).pack(side="left",anchor="ne")
327
+ tk.Button(frame, text="Zoom Out", command=zoom_out).pack(side="left",anchor="ne")
328
+ tk.Button(frame, text="←", command=pan_left).pack(side="left",anchor="ne")
329
+ tk.Button(frame, text="→", command=pan_right).pack(side="left",anchor="ne")
330
+ tk.Button(frame, text="↑", command=pan_up).pack(side="left",anchor="ne")
331
+ tk.Button(frame, text="↓", command=pan_down).pack(side="left",anchor="ne")
332
+ turtle.mainloop()
@@ -0,0 +1,56 @@
1
+ """
2
+ AxiomX.hyperbolic - the hyperbolic function module.
3
+
4
+ This module contains all hyperbolic functions and their inverses.
5
+ """
6
+
7
+ from AxiomX.exp import ln
8
+ from AxiomX.constants import e
9
+
10
+ def sinh(x):
11
+ """Returns the hyperbolic sine of x."""
12
+ return (e**x - e**(-x))/2
13
+
14
+ def cosh(x):
15
+ """Returns the hyperbolic cosine of x."""
16
+ return (e**x + e**(-x))/2
17
+
18
+ def tanh(x):
19
+ """Returns the hyperbolic tangent of x."""
20
+ return sinh(x) / cosh(x)
21
+
22
+ def coth(x):
23
+ """Returns the hyperbolic cotangent of x."""
24
+ return cosh(x) / sinh(x)
25
+
26
+ def sech(x):
27
+ """Returns the hyperbolic secant of x."""
28
+ return 1 / cosh(x)
29
+
30
+ def cosech(x):
31
+ """Returns the hyperbolic cosecant of x."""
32
+ return 1 / sinh(x)
33
+
34
+ def arcsinh(x):
35
+ """Returns the inverse hyperbolic sine of x."""
36
+ return ln(x + (x**2 + 1)**0.5)
37
+
38
+ def arccosh(x):
39
+ """Returns the inverse hyperbolic cosine of x."""
40
+ return abs(arcsinh((x**2 - 1)**0.5))
41
+
42
+ def arccoth(x):
43
+ """Returns the inverse hyperbolic tangent of x."""
44
+ return 0.5 * ln((x+1)/(x-1))
45
+
46
+ def arctanh(x):
47
+ """Returns the inverse hyperbolic cotangent of x."""
48
+ return arccoth(1/x)
49
+
50
+ def arcsech(x):
51
+ """Returns the inverse hyperbolic secant of x."""
52
+ return arccosh(1/x)
53
+
54
+ def arccosech(x):
55
+ """Returns the inverse hyperbolic cosecant of x."""
56
+ return arcsinh(1/x)