mapFolding 0.3.8__py3-none-any.whl → 0.3.10__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.
- mapFolding/__init__.py +56 -0
- mapFolding/basecamp.py +55 -0
- mapFolding/beDRY.py +376 -0
- mapFolding/oeis.py +339 -0
- mapFolding/someAssemblyRequired/__init__.py +2 -0
- {someAssemblyRequired → mapFolding/someAssemblyRequired}/makeJob.py +4 -5
- mapFolding/someAssemblyRequired/synthesizeJobNumba.py +383 -0
- mapFolding/someAssemblyRequired/synthesizeModuleJAX.py +29 -0
- {someAssemblyRequired → mapFolding/someAssemblyRequired}/synthesizeModulesNumba.py +186 -99
- syntheticModules/numbaInitialize.py → mapFolding/syntheticModules/numba_countInitialize.py +6 -9
- syntheticModules/numbaParallel.py → mapFolding/syntheticModules/numba_countParallel.py +4 -4
- syntheticModules/numbaSequential.py → mapFolding/syntheticModules/numba_countSequential.py +5 -5
- mapFolding/syntheticModules/numba_doTheNeedful.py +30 -0
- mapFolding/theDao.py +213 -0
- mapFolding/theSSOT.py +251 -0
- mapFolding/theSSOTnumba.py +115 -0
- mapFolding-0.3.10.dist-info/LICENSE +407 -0
- {mapFolding-0.3.8.dist-info → mapFolding-0.3.10.dist-info}/METADATA +9 -11
- mapFolding-0.3.10.dist-info/RECORD +40 -0
- mapFolding-0.3.10.dist-info/top_level.txt +2 -0
- tests/__init__.py +1 -0
- tests/conftest.py +183 -0
- tests/conftest_tmpRegistry.py +62 -0
- tests/conftest_uniformTests.py +53 -0
- tests/test_oeis.py +141 -0
- tests/test_other.py +259 -0
- tests/test_tasks.py +44 -0
- tests/test_types.py +5 -0
- benchmarks/benchmarking.py +0 -67
- citations/constants.py +0 -3
- citations/updateCitation.py +0 -354
- mapFolding-0.3.8.dist-info/RECORD +0 -26
- mapFolding-0.3.8.dist-info/top_level.txt +0 -5
- someAssemblyRequired/__init__.py +0 -1
- someAssemblyRequired/synthesizeModuleJobNumba.py +0 -212
- syntheticModules/__init__.py +0 -3
- {reference → mapFolding/reference}/flattened.py +0 -0
- {reference → mapFolding/reference}/hunterNumba.py +0 -0
- {reference → mapFolding/reference}/irvineJavaPort.py +0 -0
- {reference → mapFolding/reference}/jax.py +0 -0
- {reference → mapFolding/reference}/lunnan.py +0 -0
- {reference → mapFolding/reference}/lunnanNumpy.py +0 -0
- {reference → mapFolding/reference}/lunnanWhile.py +0 -0
- {reference → mapFolding/reference}/rotatedEntryPoint.py +0 -0
- {reference → mapFolding/reference}/total_countPlus1vsPlusN.py +0 -0
- {someAssemblyRequired → mapFolding/someAssemblyRequired}/getLLVMforNoReason.py +0 -0
- {mapFolding-0.3.8.dist-info → mapFolding-0.3.10.dist-info}/WHEEL +0 -0
- {mapFolding-0.3.8.dist-info → mapFolding-0.3.10.dist-info}/entry_points.txt +0 -0
|
@@ -1,18 +1,48 @@
|
|
|
1
|
-
from mapFolding import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from mapFolding import (
|
|
2
|
+
EnumIndices,
|
|
3
|
+
getAlgorithmSource,
|
|
4
|
+
getPathPackage,
|
|
5
|
+
getPathSyntheticModules,
|
|
6
|
+
hackSSOTdatatype,
|
|
7
|
+
hackSSOTdtype,
|
|
8
|
+
indexMy,
|
|
9
|
+
indexTrack,
|
|
10
|
+
moduleOfSyntheticModules,
|
|
11
|
+
myPackageNameIs,
|
|
12
|
+
ParametersNumba,
|
|
13
|
+
parametersNumbaSuperJit,
|
|
14
|
+
parametersNumbaFailEarly,
|
|
15
|
+
parametersNumbaSuperJitParallel,
|
|
16
|
+
parametersNumbaDEFAULT,
|
|
17
|
+
setDatatypeElephino,
|
|
18
|
+
setDatatypeFoldsTotal,
|
|
19
|
+
setDatatypeLeavesTotal,
|
|
20
|
+
setDatatypeModule,
|
|
21
|
+
)
|
|
22
|
+
from typing import cast, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
|
|
4
23
|
from types import ModuleType
|
|
24
|
+
from collections import namedtuple
|
|
5
25
|
import ast
|
|
6
26
|
import inspect
|
|
7
27
|
import numba
|
|
8
28
|
import numpy
|
|
9
29
|
import pathlib
|
|
10
30
|
|
|
31
|
+
youOughtaKnow = namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
|
|
32
|
+
|
|
11
33
|
"""TODO
|
|
12
34
|
Convert types
|
|
13
35
|
e.g. `groupsOfFolds: int = 0` to `groupsOfFolds = numba.types.{datatypeLarge}(0)`
|
|
14
36
|
This isn't necessary for Numba, but I may the infrastructure for other compilers or paradigms."""
|
|
15
37
|
|
|
38
|
+
def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
|
|
39
|
+
# TODO: more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
|
|
40
|
+
for decoratorItem in astCallable.decorator_list.copy():
|
|
41
|
+
import warnings
|
|
42
|
+
astCallable.decorator_list.remove(decoratorItem)
|
|
43
|
+
warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}")
|
|
44
|
+
return astCallable
|
|
45
|
+
|
|
16
46
|
class RecursiveInliner(ast.NodeTransformer):
|
|
17
47
|
"""
|
|
18
48
|
Class RecursiveInliner:
|
|
@@ -53,8 +83,8 @@ class RecursiveInliner(ast.NodeTransformer):
|
|
|
53
83
|
self.visit(astNode)
|
|
54
84
|
return inlineDefinition
|
|
55
85
|
|
|
56
|
-
def visit_Call(self,
|
|
57
|
-
callNodeVisited = self.generic_visit(
|
|
86
|
+
def visit_Call(self, node: ast.Call) -> ast.AST:
|
|
87
|
+
callNodeVisited = self.generic_visit(node)
|
|
58
88
|
if (isinstance(callNodeVisited, ast.Call) and isinstance(callNodeVisited.func, ast.Name) and callNodeVisited.func.id in self.dictionaryFunctions):
|
|
59
89
|
inlineDefinition = self.inlineFunctionBody(callNodeVisited.func.id)
|
|
60
90
|
if (inlineDefinition and inlineDefinition.body):
|
|
@@ -74,7 +104,7 @@ class RecursiveInliner(ast.NodeTransformer):
|
|
|
74
104
|
return [self.visit(stmt) for stmt in inlineDefinition.body]
|
|
75
105
|
return self.generic_visit(node)
|
|
76
106
|
|
|
77
|
-
def decorateCallableWithNumba(astCallable: ast.FunctionDef,
|
|
107
|
+
def decorateCallableWithNumba(astCallable: ast.FunctionDef, parametersNumba: Optional[ParametersNumba]=None) -> ast.FunctionDef:
|
|
78
108
|
"""
|
|
79
109
|
Decorates an AST function definition with Numba JIT compilation parameters.
|
|
80
110
|
|
|
@@ -83,6 +113,7 @@ def decorateCallableWithNumba(astCallable: ast.FunctionDef, parallel: bool=False
|
|
|
83
113
|
|
|
84
114
|
Parameters
|
|
85
115
|
----------
|
|
116
|
+
|
|
86
117
|
astCallable : ast.FunctionDef
|
|
87
118
|
The AST node representing the function to be decorated with Numba JIT.
|
|
88
119
|
parallel : bool, optional
|
|
@@ -91,6 +122,7 @@ def decorateCallableWithNumba(astCallable: ast.FunctionDef, parallel: bool=False
|
|
|
91
122
|
|
|
92
123
|
Returns
|
|
93
124
|
-------
|
|
125
|
+
|
|
94
126
|
ast.FunctionDef
|
|
95
127
|
The modified AST function definition node with added Numba decorators.
|
|
96
128
|
|
|
@@ -160,8 +192,7 @@ def decorateCallableWithNumba(astCallable: ast.FunctionDef, parallel: bool=False
|
|
|
160
192
|
|
|
161
193
|
return ast.Subscript(value=datatypeNumba, slice=shapeAST, ctx=ast.Load())
|
|
162
194
|
|
|
163
|
-
|
|
164
|
-
# callableSourceDecorators = [decorator for decorator in callableInlined.decorator_list]
|
|
195
|
+
astCallable = Z0Z_UnhandledDecorators(astCallable)
|
|
165
196
|
|
|
166
197
|
listNumbaParameterSignature: Sequence[ast.expr] = []
|
|
167
198
|
for parameter in astCallable.args.args:
|
|
@@ -169,15 +200,31 @@ def decorateCallableWithNumba(astCallable: ast.FunctionDef, parallel: bool=False
|
|
|
169
200
|
if (signatureElement):
|
|
170
201
|
listNumbaParameterSignature.append(signatureElement)
|
|
171
202
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if astCallable
|
|
175
|
-
|
|
203
|
+
astTupleSignatureParameters = ast.Tuple(elts=listNumbaParameterSignature, ctx=ast.Load())
|
|
204
|
+
|
|
205
|
+
# TODO if `astCallable` has a return, the return needs to be added to `astArgsNumbaSignature` in the appropriate place
|
|
206
|
+
# The return, when placed in the args, is treated as a `Call`. This is logical because numba is converting to machine code.
|
|
207
|
+
# , args=[Call(func=Name(id='int64', ctx=Load()))]
|
|
208
|
+
ast_argsSignature = astTupleSignatureParameters
|
|
209
|
+
|
|
210
|
+
ImaReturn = next((node for node in astCallable.body if isinstance(node, ast.Return)), None)
|
|
211
|
+
# Return(value=Name(id='groupsOfFolds', ctx=Load()))]
|
|
212
|
+
if ImaReturn is not None and isinstance(ImaReturn.value, ast.Name):
|
|
213
|
+
my_idIf_I_wereA_astCall_func_astName_idParameter = ImaReturn.value.id
|
|
214
|
+
ast_argsSignature = ast.Call(
|
|
215
|
+
func=ast.Name(id=my_idIf_I_wereA_astCall_func_astName_idParameter, ctx=ast.Load()),
|
|
216
|
+
args=[astTupleSignatureParameters],
|
|
217
|
+
keywords=[]
|
|
218
|
+
)
|
|
176
219
|
else:
|
|
177
|
-
|
|
220
|
+
ast_argsSignature = astTupleSignatureParameters
|
|
221
|
+
|
|
222
|
+
if parametersNumba is None:
|
|
223
|
+
parametersNumba = parametersNumbaDEFAULT
|
|
224
|
+
|
|
178
225
|
listKeywordsNumbaSignature = [ast.keyword(arg=parameterName, value=ast.Constant(value=parameterValue)) for parameterName, parameterValue in parametersNumba.items()]
|
|
179
226
|
|
|
180
|
-
astDecoratorNumba = ast.Call(func=ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr='jit', ctx=ast.Load()), args=[
|
|
227
|
+
astDecoratorNumba = ast.Call(func=ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr='jit', ctx=ast.Load()), args=[ast_argsSignature], keywords=listKeywordsNumbaSignature)
|
|
181
228
|
|
|
182
229
|
astCallable.decorator_list = [astDecoratorNumba]
|
|
183
230
|
return astCallable
|
|
@@ -289,7 +336,8 @@ class UnpackArrayAccesses(ast.NodeTransformer):
|
|
|
289
336
|
node.body = initializations + node.body
|
|
290
337
|
return node
|
|
291
338
|
|
|
292
|
-
def inlineOneCallable(codeSource, callableTarget):
|
|
339
|
+
def inlineOneCallable(codeSource: str, callableTarget: str):
|
|
340
|
+
|
|
293
341
|
"""
|
|
294
342
|
Inlines a target callable function and its dependencies within the provided code source.
|
|
295
343
|
|
|
@@ -326,8 +374,17 @@ def inlineOneCallable(codeSource, callableTarget):
|
|
|
326
374
|
|
|
327
375
|
if callableInlined:
|
|
328
376
|
ast.fix_missing_locations(callableInlined)
|
|
329
|
-
|
|
330
|
-
|
|
377
|
+
parametersNumba = None
|
|
378
|
+
|
|
379
|
+
match callableTarget:
|
|
380
|
+
case 'countParallel':
|
|
381
|
+
parametersNumba = parametersNumbaSuperJitParallel
|
|
382
|
+
case 'countSequential':
|
|
383
|
+
parametersNumba = parametersNumbaSuperJit
|
|
384
|
+
case 'countInitialize':
|
|
385
|
+
parametersNumba = parametersNumbaDEFAULT
|
|
386
|
+
|
|
387
|
+
callableDecorated = decorateCallableWithNumba(callableInlined, parametersNumba)
|
|
331
388
|
|
|
332
389
|
if callableTarget == 'countSequential':
|
|
333
390
|
unpackerMy = UnpackArrayAccesses(indexMy, 'my')
|
|
@@ -343,104 +400,134 @@ def inlineOneCallable(codeSource, callableTarget):
|
|
|
343
400
|
moduleSource = ast.unparse(moduleAST)
|
|
344
401
|
return moduleSource
|
|
345
402
|
|
|
346
|
-
|
|
347
|
-
"""AST transformer that validates and appends imports to __init__.py files."""
|
|
348
|
-
|
|
349
|
-
def __init__(self, listPathFilenamesDestination: list[tuple[pathlib.Path, str]]):
|
|
350
|
-
self.listPathFilenamesDestination = listPathFilenamesDestination
|
|
351
|
-
self.listTuplesDunderInit = []
|
|
352
|
-
|
|
353
|
-
def process_init_files(self) -> list[tuple[pathlib.Path, str]]:
|
|
354
|
-
for pathFilename, callableTarget in self.listPathFilenamesDestination:
|
|
355
|
-
pathDunderInit = pathFilename.parent / "__init__.py"
|
|
356
|
-
|
|
357
|
-
# Create empty init if doesn't exist
|
|
358
|
-
if not pathDunderInit.exists():
|
|
359
|
-
pathDunderInit.write_text("")
|
|
360
|
-
|
|
361
|
-
# Parse existing init file
|
|
362
|
-
try:
|
|
363
|
-
treeInit = ast.parse(pathDunderInit.read_text())
|
|
364
|
-
except SyntaxError:
|
|
365
|
-
treeInit = ast.Module(body=[], type_ignores=[])
|
|
366
|
-
|
|
367
|
-
# Compute the lowercase module target
|
|
368
|
-
moduleTarget = "." + pathFilename.stem
|
|
369
|
-
moduleTargetLower = moduleTarget.lower()
|
|
370
|
-
|
|
371
|
-
# Track existing imports as (normalizedModule, name)
|
|
372
|
-
setImportsExisting = set()
|
|
373
|
-
for node in treeInit.body:
|
|
374
|
-
if isinstance(node, ast.ImportFrom) and node.module:
|
|
375
|
-
# Compare on a lowercase basis
|
|
376
|
-
if node.module.lower() == moduleTargetLower:
|
|
377
|
-
for alias in node.names:
|
|
378
|
-
setImportsExisting.add((moduleTargetLower, alias.name))
|
|
379
|
-
|
|
380
|
-
# Only append if this exact import doesn't exist
|
|
381
|
-
if (moduleTargetLower, callableTarget) not in setImportsExisting:
|
|
382
|
-
newImport = ast.ImportFrom(
|
|
383
|
-
module=moduleTarget,
|
|
384
|
-
names=[ast.alias(name=callableTarget, asname=None)],
|
|
385
|
-
level=0
|
|
386
|
-
)
|
|
387
|
-
treeInit.body.append(newImport)
|
|
388
|
-
ast.fix_missing_locations(treeInit)
|
|
389
|
-
pathDunderInit.write_text(ast.unparse(treeInit))
|
|
390
|
-
|
|
391
|
-
self.listTuplesDunderInit.append((pathDunderInit, callableTarget))
|
|
392
|
-
|
|
393
|
-
return self.listTuplesDunderInit
|
|
394
|
-
|
|
395
|
-
def inlineMapFoldingNumba(listCallablesAsStr: List[str], algorithmSource: Optional[ModuleType] = None):
|
|
396
|
-
"""Synthesizes numba-optimized versions of map folding functions.
|
|
397
|
-
This function creates specialized versions of map folding functions by inlining
|
|
398
|
-
target callables and generating optimized modules. It handles the code generation
|
|
399
|
-
and file writing process.
|
|
403
|
+
def makeDispatcherNumba(codeSource: str, callableTarget: str, listStuffYouOughtaKnow: List[youOughtaKnow]) -> str:
|
|
400
404
|
|
|
401
|
-
|
|
402
|
-
listCallablesAsStr (List[str]): List of callable names to be processed as strings.
|
|
403
|
-
algorithmSource (Optional[ModuleType], optional): Source module containing the algorithms.
|
|
404
|
-
If None, will be obtained via getAlgorithmSource(). Defaults to None.
|
|
405
|
+
docstringDispatcherNumba = """What in tarnation is this stupid module and function?
|
|
405
406
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
407
|
+
- This function is not in the same module as `countFolds` so that we can delay Numba just-in-time (jit) compilation of this function and the finalization of its settings until we are ready.
|
|
408
|
+
- This function is not in the same module as the next function, which does the hard work, so that we can delay `numba.jit` compilation of the next function.
|
|
409
|
+
- This function is "jitted" but the next function is super jitted, which makes it too arrogant to talk to plebian Python functions. It will, however, reluctantly talk to basic jitted functions.
|
|
410
|
+
- So this module can talk to the next function, and because this module isn't as arrogant, it will talk to the low-class `countFolds` that called this function. Well, with a few restrictions, of course:
|
|
411
|
+
- No `TypedDict`
|
|
412
|
+
- The plebs must clean up their own memory problems
|
|
413
|
+
- No oversized integers
|
|
414
|
+
- No global variables, only global constants
|
|
415
|
+
- It won't accept pleb nonlocal variables either
|
|
416
|
+
- Python "class": they are all inferior to the jit class
|
|
417
|
+
- No `**kwargs`
|
|
418
|
+
- and just a few dozen-jillion other things."""
|
|
410
419
|
|
|
411
|
-
|
|
412
|
-
Exception: If inline operation fails during code generation.
|
|
420
|
+
astSource = ast.parse(codeSource)
|
|
413
421
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
422
|
+
astImports = [node for node in astSource.body if isinstance(node, (ast.Import, ast.ImportFrom))]
|
|
423
|
+
FunctionDefTarget = next((node for node in astSource.body if isinstance(node, ast.FunctionDef) and node.name == callableTarget), None)
|
|
424
|
+
|
|
425
|
+
if not FunctionDefTarget:
|
|
426
|
+
raise ValueError(f"Could not find function {callableTarget} in source code")
|
|
427
|
+
|
|
428
|
+
# Zero-out the decorator list
|
|
429
|
+
FunctionDefTarget = Z0Z_UnhandledDecorators(FunctionDefTarget)
|
|
430
|
+
|
|
431
|
+
# Add Numba decorator
|
|
432
|
+
FunctionDefTarget = decorateCallableWithNumba(FunctionDefTarget, parametersNumbaFailEarly)
|
|
433
|
+
FunctionDefTarget.body.insert(0, ast.Expr(value=ast.Constant(value=docstringDispatcherNumba)))
|
|
434
|
+
|
|
435
|
+
astModule = ast.Module(
|
|
436
|
+
body=cast(List[ast.stmt]
|
|
437
|
+
, astImports
|
|
438
|
+
+ [Don_Lapre_The_Road_to_Self_Improvement_For_Programmers_by_Using_Short_Identifiers.astForCompetentProgrammers
|
|
439
|
+
for Don_Lapre_The_Road_to_Self_Improvement_For_Programmers_by_Using_Short_Identifiers in listStuffYouOughtaKnow]
|
|
440
|
+
+ [FunctionDefTarget])
|
|
441
|
+
, type_ignores=[]
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
ast.fix_missing_locations(astModule)
|
|
445
|
+
return ast.unparse(astModule)
|
|
446
|
+
|
|
447
|
+
def makeNumbaOptimizedFlow(listCallablesInline: List[str], callableDispatcher: Optional[str] = None, algorithmSource: Optional[ModuleType] = None):
|
|
419
448
|
if not algorithmSource:
|
|
420
449
|
algorithmSource = getAlgorithmSource()
|
|
421
450
|
|
|
422
|
-
|
|
451
|
+
formatModuleNameDEFAULT = "numba_{callableTarget}"
|
|
452
|
+
|
|
453
|
+
# When I am a more competent programmer, I will make getPathFilenameWrite dependent on makeAstImport or vice versa,
|
|
454
|
+
# so the name of the physical file doesn't get out of whack with the name of the logical module.
|
|
455
|
+
def getPathFilenameWrite(callableTarget: str
|
|
456
|
+
, pathWrite: Optional[pathlib.Path] = None
|
|
457
|
+
, formatFilenameWrite: Optional[str] = None
|
|
458
|
+
) -> pathlib.Path:
|
|
459
|
+
if not pathWrite:
|
|
460
|
+
pathWrite = getPathSyntheticModules()
|
|
461
|
+
if not formatFilenameWrite:
|
|
462
|
+
formatFilenameWrite = formatModuleNameDEFAULT + '.py'
|
|
463
|
+
|
|
464
|
+
pathFilename = pathWrite / formatFilenameWrite.format(callableTarget=callableTarget)
|
|
465
|
+
return pathFilename
|
|
466
|
+
|
|
467
|
+
def makeAstImport(callableTarget: str
|
|
468
|
+
, packageName: Optional[str] = None
|
|
469
|
+
, subPackageName: Optional[str] = None
|
|
470
|
+
, moduleName: Optional[str] = None
|
|
471
|
+
, astNodeLogicalPathThingy: Optional[ast.AST] = None
|
|
472
|
+
) -> ast.ImportFrom:
|
|
473
|
+
"""Creates import AST node for synthetic modules."""
|
|
474
|
+
if astNodeLogicalPathThingy is None:
|
|
475
|
+
if packageName is None:
|
|
476
|
+
packageName = myPackageNameIs
|
|
477
|
+
if subPackageName is None:
|
|
478
|
+
subPackageName = moduleOfSyntheticModules
|
|
479
|
+
if moduleName is None:
|
|
480
|
+
moduleName = formatModuleNameDEFAULT.format(callableTarget=callableTarget)
|
|
481
|
+
module=f'{packageName}.{subPackageName}.{moduleName}'
|
|
482
|
+
else:
|
|
483
|
+
module = str(astNodeLogicalPathThingy)
|
|
484
|
+
return ast.ImportFrom(
|
|
485
|
+
module=module,
|
|
486
|
+
names=[ast.alias(name=callableTarget, asname=None)],
|
|
487
|
+
level=0
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
listStuffYouOughtaKnow: List[youOughtaKnow] = []
|
|
491
|
+
|
|
492
|
+
for callableTarget in listCallablesInline:
|
|
493
|
+
codeSource = inspect.getsource(algorithmSource)
|
|
494
|
+
moduleSource = inlineOneCallable(codeSource, callableTarget)
|
|
495
|
+
if not moduleSource:
|
|
496
|
+
raise Exception("Pylance, OMG! The sky is falling!")
|
|
423
497
|
|
|
424
|
-
|
|
425
|
-
|
|
498
|
+
pathFilename = getPathFilenameWrite(callableTarget)
|
|
499
|
+
astImport = makeAstImport(callableTarget)
|
|
426
500
|
|
|
427
|
-
|
|
501
|
+
listStuffYouOughtaKnow.append(youOughtaKnow(
|
|
502
|
+
callableSynthesized=callableTarget,
|
|
503
|
+
pathFilenameForMe=pathFilename,
|
|
504
|
+
astForCompetentProgrammers=astImport
|
|
505
|
+
))
|
|
506
|
+
pathFilename.write_text(moduleSource)
|
|
507
|
+
|
|
508
|
+
# Generate dispatcher if requested
|
|
509
|
+
if callableDispatcher:
|
|
428
510
|
codeSource = inspect.getsource(algorithmSource)
|
|
429
|
-
moduleSource =
|
|
511
|
+
moduleSource = makeDispatcherNumba(codeSource, callableDispatcher, listStuffYouOughtaKnow)
|
|
430
512
|
if not moduleSource:
|
|
431
513
|
raise Exception("Pylance, OMG! The sky is falling!")
|
|
432
|
-
pathFilenameAlgorithm = pathlib.Path(inspect.getfile(algorithmSource))
|
|
433
|
-
pathFilenameDestination = pathFilenameAlgorithm.parent / relativePathSyntheticModules / pathFilenameAlgorithm.with_stem("numba"+callableTarget[5:None]).name
|
|
434
|
-
pathFilenameDestination.write_text(moduleSource)
|
|
435
|
-
listPathFilenamesDestination.append((pathFilenameDestination, callableTarget))
|
|
436
514
|
|
|
437
|
-
|
|
438
|
-
|
|
515
|
+
pathFilename = getPathFilenameWrite(callableDispatcher)
|
|
516
|
+
astImport = makeAstImport(callableDispatcher)
|
|
517
|
+
|
|
518
|
+
listStuffYouOughtaKnow.append(youOughtaKnow(
|
|
519
|
+
callableSynthesized=callableDispatcher,
|
|
520
|
+
pathFilenameForMe=pathFilename,
|
|
521
|
+
astForCompetentProgrammers=astImport
|
|
522
|
+
))
|
|
523
|
+
pathFilename.write_text(moduleSource)
|
|
439
524
|
|
|
440
525
|
if __name__ == '__main__':
|
|
441
|
-
listCallablesAsStr: List[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
442
526
|
setDatatypeModule('numpy', sourGrapes=True)
|
|
443
527
|
setDatatypeFoldsTotal('int64', sourGrapes=True)
|
|
444
528
|
setDatatypeElephino('uint8', sourGrapes=True)
|
|
445
529
|
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
446
|
-
|
|
530
|
+
listCallablesInline: List[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
531
|
+
callableDispatcher = 'doTheNeedful'
|
|
532
|
+
makeNumbaOptimizedFlow(listCallablesInline, callableDispatcher)
|
|
533
|
+
# makeNumbaOptimizedFlow(listCallablesInline)
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import numpy
|
|
2
1
|
from typing import Any, Tuple
|
|
3
|
-
|
|
4
|
-
from
|
|
2
|
+
import numpy
|
|
3
|
+
from numpy import dtype, integer, ndarray
|
|
5
4
|
import numba
|
|
5
|
+
from mapFolding import indexMy, indexTrack
|
|
6
6
|
|
|
7
|
-
@numba.jit((numba.uint8[:, :, ::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]))
|
|
8
|
-
def countInitialize(connectionGraph:
|
|
9
|
-
, gapsWhere: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]]
|
|
10
|
-
, my: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]]
|
|
11
|
-
, track: numpy.ndarray[Tuple[int, int], numpy.dtype[integer[Any]]]):
|
|
7
|
+
@numba.jit((numba.uint8[:, :, ::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
|
|
8
|
+
def countInitialize(connectionGraph: ndarray[Tuple[int, int, int], dtype[integer[Any]]], gapsWhere: ndarray[Tuple[int], dtype[integer[Any]]], my: ndarray[Tuple[int], dtype[integer[Any]]], track: ndarray[Tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
12
9
|
while my[indexMy.leaf1ndex.value]:
|
|
13
10
|
if my[indexMy.leaf1ndex.value] <= 1 or track[indexTrack.leafBelow.value, 0] == 1:
|
|
14
11
|
my[indexMy.dimensionsUnconstrained.value] = my[indexMy.dimensionsTotal.value]
|
|
@@ -48,4 +45,4 @@ def countInitialize(connectionGraph: numpy.ndarray[Tuple[int, int, int], numpy.d
|
|
|
48
45
|
track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
|
|
49
46
|
my[indexMy.leaf1ndex.value] += 1
|
|
50
47
|
if my[indexMy.gap1ndex.value] > 0:
|
|
51
|
-
return
|
|
48
|
+
return
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
from mapFolding import indexMy, indexTrack
|
|
1
2
|
from typing import Any, Tuple
|
|
2
|
-
from numpy import integer
|
|
3
3
|
import numpy
|
|
4
|
-
from
|
|
4
|
+
from numpy import dtype, integer, ndarray
|
|
5
5
|
import numba
|
|
6
6
|
|
|
7
|
-
@numba.jit((numba.uint8[:, :, ::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=
|
|
8
|
-
def countParallel(connectionGraph:
|
|
7
|
+
@numba.jit((numba.uint8[:, :, ::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=True)
|
|
8
|
+
def countParallel(connectionGraph: ndarray[Tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[Tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[Tuple[int], dtype[integer[Any]]], my: ndarray[Tuple[int], dtype[integer[Any]]], track: ndarray[Tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
9
9
|
gapsWherePARALLEL = gapsWhere.copy()
|
|
10
10
|
myPARALLEL = my.copy()
|
|
11
11
|
trackPARALLEL = track.copy()
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from typing import Any, Tuple
|
|
2
|
-
from numpy import integer
|
|
3
1
|
import numpy
|
|
4
|
-
from
|
|
2
|
+
from numpy import dtype, integer, ndarray
|
|
5
3
|
import numba
|
|
4
|
+
from mapFolding import indexMy, indexTrack
|
|
5
|
+
from typing import Any, Tuple
|
|
6
6
|
|
|
7
|
-
@numba.jit((numba.uint8[:, :, ::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=
|
|
8
|
-
def countSequential(connectionGraph:
|
|
7
|
+
@numba.jit((numba.uint8[:, :, ::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=False, cache=True, error_model='numpy', fastmath=True, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=False)
|
|
8
|
+
def countSequential(connectionGraph: ndarray[Tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[Tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[Tuple[int], dtype[integer[Any]]], my: ndarray[Tuple[int], dtype[integer[Any]]], track: ndarray[Tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
9
9
|
leafBelow = track[indexTrack.leafBelow.value]
|
|
10
10
|
gapRangeStart = track[indexTrack.gapRangeStart.value]
|
|
11
11
|
countDimensionsGapped = track[indexTrack.countDimensionsGapped.value]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from mapFolding import indexMy, indexTrack
|
|
2
|
+
from numpy import dtype, integer, ndarray
|
|
3
|
+
from typing import Any, Tuple
|
|
4
|
+
import numba
|
|
5
|
+
import numpy
|
|
6
|
+
from mapFolding.syntheticModules.numba_countInitialize import countInitialize
|
|
7
|
+
from mapFolding.syntheticModules.numba_countParallel import countParallel
|
|
8
|
+
from mapFolding.syntheticModules.numba_countSequential import countSequential
|
|
9
|
+
|
|
10
|
+
@numba.jit((numba.uint8[:, :, ::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:, ::1]), _nrt=True, boundscheck=True, cache=True, error_model='python', fastmath=False, forceinline=True, inline='always', looplift=False, no_cfunc_wrapper=False, no_cpython_wrapper=False, nopython=True, parallel=False)
|
|
11
|
+
def doTheNeedful(connectionGraph: ndarray[Tuple[int, int, int], dtype[integer[Any]]], foldGroups: ndarray[Tuple[int], dtype[integer[Any]]], gapsWhere: ndarray[Tuple[int], dtype[integer[Any]]], mapShape: ndarray[Tuple[int], dtype[integer[Any]]], my: ndarray[Tuple[int], dtype[integer[Any]]], track: ndarray[Tuple[int, int], dtype[integer[Any]]]) -> None:
|
|
12
|
+
"""What in tarnation is this stupid module and function?
|
|
13
|
+
|
|
14
|
+
- This function is not in the same module as `countFolds` so that we can delay Numba just-in-time (jit) compilation of this function and the finalization of its settings until we are ready.
|
|
15
|
+
- This function is not in the same module as the next function, which does the hard work, so that we can delay `numba.jit` compilation of the next function.
|
|
16
|
+
- This function is "jitted" but the next function is super jitted, which makes it too arrogant to talk to plebian Python functions. It will, however, reluctantly talk to basic jitted functions.
|
|
17
|
+
- So this module can talk to the next function, and because this module isn't as arrogant, it will talk to the low-class `countFolds` that called this function. Well, with a few restrictions, of course:
|
|
18
|
+
- No `TypedDict`
|
|
19
|
+
- The plebs must clean up their own memory problems
|
|
20
|
+
- No oversized integers
|
|
21
|
+
- No global variables, only global constants
|
|
22
|
+
- It won't accept pleb nonlocal variables either
|
|
23
|
+
- Python "class": they are all inferior to the jit class
|
|
24
|
+
- No `**kwargs`
|
|
25
|
+
- and just a few dozen-jillion other things."""
|
|
26
|
+
countInitialize(connectionGraph, gapsWhere, my, track)
|
|
27
|
+
if my[indexMy.taskDivisions.value] > 0:
|
|
28
|
+
countParallel(connectionGraph, foldGroups, gapsWhere, my, track)
|
|
29
|
+
else:
|
|
30
|
+
countSequential(connectionGraph, foldGroups, gapsWhere, my, track)
|