klongpy 0.6.9__py3-none-any.whl → 0.7.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.
Files changed (70) hide show
  1. klongpy/__init__.py +17 -1
  2. klongpy/adverbs.py +84 -82
  3. klongpy/autograd.py +299 -0
  4. klongpy/backend.py +38 -103
  5. klongpy/backends/__init__.py +26 -0
  6. klongpy/backends/base.py +469 -0
  7. klongpy/backends/numpy_backend.py +123 -0
  8. klongpy/backends/registry.py +76 -0
  9. klongpy/backends/torch_backend.py +1047 -0
  10. klongpy-0.6.9.data/scripts/kgpy → klongpy/cli.py +110 -90
  11. klongpy/core.py +113 -974
  12. klongpy/db/sys_fn_db.py +7 -6
  13. klongpy/db/sys_fn_kvs.py +2 -4
  14. klongpy/dyads.py +332 -160
  15. klongpy/interpreter.py +60 -15
  16. klongpy/monads.py +121 -75
  17. klongpy/parser.py +328 -0
  18. klongpy/repl.py +23 -5
  19. klongpy/sys_fn.py +170 -21
  20. klongpy/sys_fn_autograd.py +290 -0
  21. klongpy/sys_fn_ipc.py +22 -15
  22. klongpy/sys_fn_timer.py +13 -3
  23. klongpy/types.py +503 -0
  24. klongpy/web/sys_fn_web.py +14 -4
  25. klongpy/writer.py +122 -0
  26. klongpy/ws/sys_fn_ws.py +5 -8
  27. klongpy-0.7.1.dist-info/METADATA +544 -0
  28. klongpy-0.7.1.dist-info/RECORD +52 -0
  29. {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/WHEEL +1 -1
  30. klongpy-0.7.1.dist-info/entry_points.txt +2 -0
  31. {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/top_level.txt +0 -1
  32. klongpy-0.6.9.dist-info/METADATA +0 -448
  33. klongpy-0.6.9.dist-info/RECORD +0 -77
  34. tests/__init__.py +0 -6
  35. tests/gen_join_over.py +0 -119
  36. tests/gen_py_suite.py +0 -77
  37. tests/gen_test_fn.py +0 -259
  38. tests/perf_async.py +0 -25
  39. tests/perf_avg.py +0 -18
  40. tests/perf_duckdb.py +0 -32
  41. tests/perf_gen.py +0 -38
  42. tests/perf_ipc_overhead.py +0 -34
  43. tests/perf_join.py +0 -53
  44. tests/perf_load.py +0 -17
  45. tests/perf_prog.py +0 -18
  46. tests/perf_serdes.py +0 -52
  47. tests/perf_sys_fn_db.py +0 -263
  48. tests/perf_vector.py +0 -40
  49. tests/test_accel.py +0 -227
  50. tests/test_df_cache.py +0 -85
  51. tests/test_eval_monad_list.py +0 -34
  52. tests/test_examples.py +0 -64
  53. tests/test_extra_suite.py +0 -382
  54. tests/test_file_cache.py +0 -185
  55. tests/test_interop.py +0 -180
  56. tests/test_kg_asarray.py +0 -94
  57. tests/test_kgtests.py +0 -65
  58. tests/test_known_bugs.py +0 -206
  59. tests/test_prog.py +0 -107
  60. tests/test_reshape_strings.py +0 -33
  61. tests/test_suite.py +0 -1480
  62. tests/test_suite_file.py +0 -153
  63. tests/test_sys_fn.py +0 -420
  64. tests/test_sys_fn_db.py +0 -88
  65. tests/test_sys_fn_ipc.py +0 -587
  66. tests/test_sys_fn_timer.py +0 -133
  67. tests/test_sys_fn_web.py +0 -50
  68. tests/test_util.py +0 -233
  69. tests/utils.py +0 -126
  70. {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,123 @@
1
+ """
2
+ NumPy backend provider for KlongPy.
3
+
4
+ This is the default backend that supports all Klong operations including
5
+ string manipulation and object dtype arrays.
6
+ """
7
+ import warnings
8
+ import numpy as np
9
+
10
+ from .base import BackendProvider
11
+
12
+ # numpy 2.x moved VisibleDeprecationWarning to numpy.exceptions
13
+ from numpy.exceptions import VisibleDeprecationWarning as NumpyVisibleDeprecationWarning
14
+
15
+
16
+ class KGChar(str):
17
+ """Character type for Klong."""
18
+ pass
19
+
20
+
21
+ class NumpyBackendProvider(BackendProvider):
22
+ """NumPy-based backend provider."""
23
+
24
+ def __init__(self, device=None):
25
+ if device is not None:
26
+ raise ValueError("Backend 'numpy' does not support device selection")
27
+ self._np = np
28
+ np.seterr(divide='ignore')
29
+ warnings.filterwarnings("error", category=NumpyVisibleDeprecationWarning)
30
+ # Add isarray method to numpy module reference
31
+ self._np.isarray = lambda x: isinstance(x, np.ndarray)
32
+
33
+ @property
34
+ def name(self) -> str:
35
+ return 'numpy'
36
+
37
+ @property
38
+ def np(self):
39
+ return self._np
40
+
41
+ def supports_object_dtype(self) -> bool:
42
+ return True
43
+
44
+ def supports_strings(self) -> bool:
45
+ return True
46
+
47
+ def supports_float64(self) -> bool:
48
+ return True
49
+
50
+ def is_array(self, x) -> bool:
51
+ return isinstance(x, np.ndarray)
52
+
53
+ def is_backend_array(self, x) -> bool:
54
+ return False # numpy arrays are the base case, not a "backend" type
55
+
56
+ def get_dtype_kind(self, arr) -> str:
57
+ if hasattr(arr, 'dtype') and hasattr(arr.dtype, 'kind'):
58
+ return arr.dtype.kind
59
+ return None
60
+
61
+ def to_numpy(self, x):
62
+ # Already numpy, just return as-is
63
+ return x
64
+
65
+ def is_scalar_integer(self, x) -> bool:
66
+ if isinstance(x, np.ndarray) and x.ndim == 0:
67
+ return np.issubdtype(x.dtype, np.integer)
68
+ return False
69
+
70
+ def is_scalar_float(self, x) -> bool:
71
+ if isinstance(x, np.ndarray) and x.ndim == 0:
72
+ return np.issubdtype(x.dtype, np.floating)
73
+ return False
74
+
75
+ def argsort(self, a, descending=False):
76
+ """Return indices that would sort the array."""
77
+ indices = np.argsort(a)
78
+ if descending:
79
+ indices = indices[::-1].copy()
80
+ return indices
81
+
82
+ def array_size(self, a):
83
+ """Get the total number of elements in an array."""
84
+ if hasattr(a, 'size'):
85
+ return a.size
86
+ return len(a) if hasattr(a, '__len__') else 1
87
+
88
+ def safe_equal(self, x, y):
89
+ """Compare two values for equality."""
90
+ return np.asarray(x, dtype=object) == np.asarray(y, dtype=object)
91
+
92
+ def to_int_array(self, a):
93
+ """Convert array to integer type."""
94
+ return np.asarray(a, dtype=int) if self.is_array(a) else int(a)
95
+
96
+ def power(self, a, b):
97
+ """Compute a^b, returning integer if result is whole number."""
98
+ r = np.power(float(a) if isinstance(a, (int, np.integer)) else a, b)
99
+ return r
100
+
101
+ def str_to_char_array(self, s):
102
+ """Convert string to character array."""
103
+ return self._np.asarray([KGChar(x) for x in s], dtype=object)
104
+
105
+ def kg_asarray(self, a):
106
+ """Convert input to numpy array, handling strings and jagged/nested data."""
107
+ if isinstance(a, str):
108
+ return self.str_to_char_array(a)
109
+ try:
110
+ arr = self._np.asarray(a)
111
+ if arr.dtype.kind not in ['O', 'i', 'f']:
112
+ raise ValueError
113
+ except (NumpyVisibleDeprecationWarning, ValueError):
114
+ try:
115
+ arr = self._np.asarray(a, dtype=object)
116
+ except ValueError:
117
+ arr = [x.tolist() if self.is_array(x) else x for x in a]
118
+ arr = self._np.asarray(arr, dtype=object)
119
+ arr = self._np.asarray(
120
+ [self.kg_asarray(x) if isinstance(x, list) else x for x in arr],
121
+ dtype=object
122
+ )
123
+ return arr
@@ -0,0 +1,76 @@
1
+ """
2
+ Backend registry for KlongPy.
3
+
4
+ Owns backend registration, lookup, and lazy torch loading.
5
+ """
6
+ import importlib
7
+ import importlib.util
8
+
9
+ from .base import BackendProvider
10
+ from .numpy_backend import NumpyBackendProvider
11
+
12
+ # Registry of available backends
13
+ _BACKENDS = {}
14
+
15
+ # Default backend name
16
+ _DEFAULT_BACKEND = 'numpy'
17
+
18
+ _TORCH_AVAILABLE = importlib.util.find_spec("torch") is not None
19
+ _TORCH_BACKEND_LOADED = False
20
+ TorchBackendProvider = None
21
+
22
+
23
+ def register_backend(name: str, provider_class):
24
+ """Register a backend provider class."""
25
+ _BACKENDS[name] = provider_class
26
+
27
+
28
+ def _load_torch_backend():
29
+ global _TORCH_BACKEND_LOADED, TorchBackendProvider
30
+ if _TORCH_BACKEND_LOADED or not _TORCH_AVAILABLE:
31
+ return
32
+ _torch_backend = importlib.import_module("klongpy.backends.torch_backend")
33
+ TorchBackendProvider = _torch_backend.TorchBackendProvider
34
+ register_backend('torch', TorchBackendProvider)
35
+ _TORCH_BACKEND_LOADED = True
36
+
37
+
38
+ def get_backend(name: str = None, **kwargs) -> BackendProvider:
39
+ """
40
+ Get a backend provider instance.
41
+
42
+ Parameters
43
+ ----------
44
+ name : str, optional
45
+ Backend name ('numpy' or 'torch'). If None, uses default.
46
+ **kwargs
47
+ Additional arguments passed to the backend provider constructor.
48
+
49
+ Returns
50
+ -------
51
+ BackendProvider
52
+ The backend provider instance.
53
+ """
54
+ if name is None:
55
+ name = _DEFAULT_BACKEND
56
+
57
+ if name == 'torch':
58
+ _load_torch_backend()
59
+
60
+ if name not in _BACKENDS:
61
+ available = ', '.join(_BACKENDS.keys())
62
+ raise ValueError(f"Unknown backend: '{name}'. Available: {available}")
63
+
64
+ return _BACKENDS[name](**kwargs)
65
+
66
+
67
+ def list_backends():
68
+ """Return list of available backend names."""
69
+ backends = list(_BACKENDS.keys())
70
+ if _TORCH_AVAILABLE and 'torch' not in backends:
71
+ backends.append('torch')
72
+ return backends
73
+
74
+
75
+ # Register built-in backends
76
+ register_backend('numpy', NumpyBackendProvider)