jjinx 0.0.1__py3-none-any.whl
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.
- jinx/__init__.py +0 -0
- jinx/errors.py +41 -0
- jinx/execution/executor.py +60 -0
- jinx/execution/jax/__init__.py +45 -0
- jinx/execution/jax/adverbs.py +91 -0
- jinx/execution/jax/application.py +231 -0
- jinx/execution/jax/verbs.py +90 -0
- jinx/execution/numpy/__init__.py +29 -0
- jinx/execution/numpy/adverbs.py +334 -0
- jinx/execution/numpy/application.py +343 -0
- jinx/execution/numpy/conjunctions.py +437 -0
- jinx/execution/numpy/conversion.py +62 -0
- jinx/execution/numpy/helpers.py +158 -0
- jinx/execution/numpy/printing.py +179 -0
- jinx/execution/numpy/verbs.py +850 -0
- jinx/primitives.py +490 -0
- jinx/shell.py +68 -0
- jinx/vocabulary.py +181 -0
- jinx/word_evaluation.py +375 -0
- jinx/word_formation.py +229 -0
- jinx/word_spelling.py +118 -0
- jjinx-0.0.1.dist-info/METADATA +148 -0
- jjinx-0.0.1.dist-info/RECORD +27 -0
- jjinx-0.0.1.dist-info/WHEEL +5 -0
- jjinx-0.0.1.dist-info/entry_points.txt +2 -0
- jjinx-0.0.1.dist-info/licenses/LICENSE +21 -0
- jjinx-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
"""Methods for printing nouns (arrays, atoms)."""
|
2
|
+
|
3
|
+
import itertools
|
4
|
+
import os
|
5
|
+
from typing import Sequence
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
from jinx.execution.numpy.helpers import is_box
|
9
|
+
from jinx.vocabulary import Noun
|
10
|
+
|
11
|
+
MAX_COLS = 100
|
12
|
+
|
13
|
+
|
14
|
+
def noun_to_string(noun: Noun[np.ndarray], max_cols: int = MAX_COLS) -> str:
|
15
|
+
"""Convert a noun to a string representation."""
|
16
|
+
arr = noun.implementation
|
17
|
+
rows = array_to_rows(arr, max_cols=max_cols)
|
18
|
+
return os.linesep.join(rows)
|
19
|
+
|
20
|
+
|
21
|
+
def array_to_rows(arr: np.ndarray, max_cols: int = MAX_COLS) -> list[str]:
|
22
|
+
"""Convert an array to a list of strings for printing."""
|
23
|
+
arr = np.atleast_1d(arr)
|
24
|
+
|
25
|
+
if arr.size == 0:
|
26
|
+
return [""]
|
27
|
+
|
28
|
+
if is_box(arr):
|
29
|
+
return box_to_rows(arr)
|
30
|
+
|
31
|
+
if arr.shape[-1] > max_cols:
|
32
|
+
arr = arr[..., :max_cols]
|
33
|
+
append_ellipsis = True
|
34
|
+
else:
|
35
|
+
append_ellipsis = False
|
36
|
+
|
37
|
+
if np.issubdtype(arr.dtype, np.floating):
|
38
|
+
rounded = [format_float(n) for n in arr.ravel().tolist()]
|
39
|
+
arr = np.asarray(rounded).reshape(arr.shape)
|
40
|
+
|
41
|
+
elif np.issubdtype(arr.dtype, np.bool_):
|
42
|
+
arr = arr.view(np.int8)
|
43
|
+
|
44
|
+
elif (
|
45
|
+
np.issubdtype(arr.dtype, np.str_) and arr.dtype.itemsize == arr.dtype.alignment
|
46
|
+
):
|
47
|
+
width = arr.shape[-1]
|
48
|
+
arr = arr.view(f"{arr.dtype.byteorder}{arr.dtype.kind}{width}")
|
49
|
+
|
50
|
+
arr_str = arr.astype(str)
|
51
|
+
|
52
|
+
if np.issubdtype(arr.dtype, np.number):
|
53
|
+
arr_str = np.strings.replace(arr_str, "-", "_")
|
54
|
+
|
55
|
+
lengths = np.strings.str_len(arr_str)
|
56
|
+
justify = np.max(lengths, axis=tuple(range(arr.ndim - 1)))
|
57
|
+
arr_str = np.strings.rjust(arr_str, justify)
|
58
|
+
return ndim_n_to_rows(arr_str, append_ellipsis=append_ellipsis)
|
59
|
+
|
60
|
+
|
61
|
+
def get_decimal_places(n: float) -> int:
|
62
|
+
n = abs(n)
|
63
|
+
if n < 1:
|
64
|
+
return 6
|
65
|
+
if n < 10:
|
66
|
+
return 5
|
67
|
+
if n < 100:
|
68
|
+
return 4
|
69
|
+
if n < 1000:
|
70
|
+
return 3
|
71
|
+
if n < 10000:
|
72
|
+
return 2
|
73
|
+
if n < 100000:
|
74
|
+
return 1
|
75
|
+
return 0
|
76
|
+
|
77
|
+
|
78
|
+
def format_float(n: float) -> str:
|
79
|
+
if np.isinf(n):
|
80
|
+
return "__" if n < 0 else "_"
|
81
|
+
if n.is_integer():
|
82
|
+
return f"{int(n)}"
|
83
|
+
decimal_places = get_decimal_places(n)
|
84
|
+
rounded_n = round(n, decimal_places)
|
85
|
+
return f"{rounded_n}"
|
86
|
+
|
87
|
+
|
88
|
+
def ndim_1_to_str(arr: np.ndarray, append_ellipsis: bool) -> str:
|
89
|
+
result = " ".join(arr.tolist())
|
90
|
+
if append_ellipsis:
|
91
|
+
result += " ..."
|
92
|
+
return result
|
93
|
+
|
94
|
+
|
95
|
+
def ndim_n_to_rows(arr: np.ndarray, append_ellipsis: bool) -> list[str]:
|
96
|
+
if arr.ndim == 1:
|
97
|
+
return [ndim_1_to_str(arr, append_ellipsis)]
|
98
|
+
|
99
|
+
rows = []
|
100
|
+
for n, item in enumerate(arr):
|
101
|
+
if item.ndim == 1:
|
102
|
+
rows.append(ndim_1_to_str(item, append_ellipsis))
|
103
|
+
else:
|
104
|
+
rows.extend(ndim_n_to_rows(item, append_ellipsis))
|
105
|
+
if n < len(arr) - 1:
|
106
|
+
rows.extend([""] * (arr.ndim - 2))
|
107
|
+
return rows
|
108
|
+
|
109
|
+
|
110
|
+
BatchedRowsT = Sequence[str] | Sequence["BatchedRowsT"]
|
111
|
+
|
112
|
+
|
113
|
+
def box_1D_or_2D_to_rows(box: BatchedRowsT, widths: list[int]) -> list[str]:
|
114
|
+
"""Convert a 2D box (list of list of strings) to a list of strings for printing."""
|
115
|
+
rows = [box_top_line(widths=widths)]
|
116
|
+
for n, box_row in enumerate(box):
|
117
|
+
for row_item_row in itertools.zip_longest(*box_row, fillvalue=""):
|
118
|
+
vals = [str(val).ljust(width) for val, width in zip(row_item_row, widths)]
|
119
|
+
row = "│" + "│".join(vals) + "│"
|
120
|
+
rows.append(row)
|
121
|
+
|
122
|
+
if n < len(box) - 1:
|
123
|
+
rows.append(box_row_divider_line(widths=widths))
|
124
|
+
|
125
|
+
rows.append(box_bottom_line(widths=widths))
|
126
|
+
return rows
|
127
|
+
|
128
|
+
|
129
|
+
def box_to_rows(box: np.ndarray) -> list[str]:
|
130
|
+
"""Convert a box to a list of strings for printing."""
|
131
|
+
box_items = [item[0] for item in box.ravel()]
|
132
|
+
items_as_rows = [array_to_rows(item) for item in box_items]
|
133
|
+
|
134
|
+
row_groups: BatchedRowsT = list(
|
135
|
+
itertools.batched(items_as_rows, box.shape[-1], strict=True)
|
136
|
+
)
|
137
|
+
if box.ndim >= 2:
|
138
|
+
row_groups = list(itertools.batched(row_groups, box.shape[-2], strict=True))
|
139
|
+
|
140
|
+
item_widths = np.array([len(rows[0]) for rows in items_as_rows]).reshape(box.shape)
|
141
|
+
widths = np.max(item_widths, axis=tuple(range(box.ndim - 1))).tolist()
|
142
|
+
|
143
|
+
if box.ndim == 1:
|
144
|
+
return box_1D_or_2D_to_rows(row_groups, widths)
|
145
|
+
|
146
|
+
if box.ndim == 2:
|
147
|
+
return box_1D_or_2D_to_rows(row_groups[0], widths)
|
148
|
+
|
149
|
+
boxes: BatchedRowsT = [box_1D_or_2D_to_rows(rows, widths) for rows in row_groups]
|
150
|
+
leading_dims = list(box.shape[:-2])
|
151
|
+
|
152
|
+
while leading_dims:
|
153
|
+
boxes = list(itertools.batched(boxes, leading_dims.pop(), strict=True))
|
154
|
+
|
155
|
+
rows = []
|
156
|
+
|
157
|
+
def flatten_to_rows(box_list, gap_size):
|
158
|
+
for n, bxs in enumerate(box_list):
|
159
|
+
if isinstance(bxs, str):
|
160
|
+
rows.append(bxs)
|
161
|
+
else:
|
162
|
+
flatten_to_rows(bxs, gap_size - 1)
|
163
|
+
if n < len(box_list) - 1:
|
164
|
+
rows.extend([""] * gap_size)
|
165
|
+
|
166
|
+
flatten_to_rows(boxes[0], box.ndim - 2)
|
167
|
+
return rows
|
168
|
+
|
169
|
+
|
170
|
+
def box_top_line(widths: list[int]) -> str:
|
171
|
+
return "┌" + "┬".join(["─" * width for width in widths]) + "┐"
|
172
|
+
|
173
|
+
|
174
|
+
def box_row_divider_line(widths: list[int]) -> str:
|
175
|
+
return "├" + "┼".join(["─" * width for width in widths]) + "┤"
|
176
|
+
|
177
|
+
|
178
|
+
def box_bottom_line(widths: list[int]) -> str:
|
179
|
+
return "└" + "┴".join(["─" * width for width in widths]) + "┘"
|