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.
Files changed (48) hide show
  1. mapFolding/__init__.py +56 -0
  2. mapFolding/basecamp.py +55 -0
  3. mapFolding/beDRY.py +376 -0
  4. mapFolding/oeis.py +339 -0
  5. mapFolding/someAssemblyRequired/__init__.py +2 -0
  6. {someAssemblyRequired → mapFolding/someAssemblyRequired}/makeJob.py +4 -5
  7. mapFolding/someAssemblyRequired/synthesizeJobNumba.py +383 -0
  8. mapFolding/someAssemblyRequired/synthesizeModuleJAX.py +29 -0
  9. {someAssemblyRequired → mapFolding/someAssemblyRequired}/synthesizeModulesNumba.py +186 -99
  10. syntheticModules/numbaInitialize.py → mapFolding/syntheticModules/numba_countInitialize.py +6 -9
  11. syntheticModules/numbaParallel.py → mapFolding/syntheticModules/numba_countParallel.py +4 -4
  12. syntheticModules/numbaSequential.py → mapFolding/syntheticModules/numba_countSequential.py +5 -5
  13. mapFolding/syntheticModules/numba_doTheNeedful.py +30 -0
  14. mapFolding/theDao.py +213 -0
  15. mapFolding/theSSOT.py +251 -0
  16. mapFolding/theSSOTnumba.py +115 -0
  17. mapFolding-0.3.10.dist-info/LICENSE +407 -0
  18. {mapFolding-0.3.8.dist-info → mapFolding-0.3.10.dist-info}/METADATA +9 -11
  19. mapFolding-0.3.10.dist-info/RECORD +40 -0
  20. mapFolding-0.3.10.dist-info/top_level.txt +2 -0
  21. tests/__init__.py +1 -0
  22. tests/conftest.py +183 -0
  23. tests/conftest_tmpRegistry.py +62 -0
  24. tests/conftest_uniformTests.py +53 -0
  25. tests/test_oeis.py +141 -0
  26. tests/test_other.py +259 -0
  27. tests/test_tasks.py +44 -0
  28. tests/test_types.py +5 -0
  29. benchmarks/benchmarking.py +0 -67
  30. citations/constants.py +0 -3
  31. citations/updateCitation.py +0 -354
  32. mapFolding-0.3.8.dist-info/RECORD +0 -26
  33. mapFolding-0.3.8.dist-info/top_level.txt +0 -5
  34. someAssemblyRequired/__init__.py +0 -1
  35. someAssemblyRequired/synthesizeModuleJobNumba.py +0 -212
  36. syntheticModules/__init__.py +0 -3
  37. {reference → mapFolding/reference}/flattened.py +0 -0
  38. {reference → mapFolding/reference}/hunterNumba.py +0 -0
  39. {reference → mapFolding/reference}/irvineJavaPort.py +0 -0
  40. {reference → mapFolding/reference}/jax.py +0 -0
  41. {reference → mapFolding/reference}/lunnan.py +0 -0
  42. {reference → mapFolding/reference}/lunnanNumpy.py +0 -0
  43. {reference → mapFolding/reference}/lunnanWhile.py +0 -0
  44. {reference → mapFolding/reference}/rotatedEntryPoint.py +0 -0
  45. {reference → mapFolding/reference}/total_countPlus1vsPlusN.py +0 -0
  46. {someAssemblyRequired → mapFolding/someAssemblyRequired}/getLLVMforNoReason.py +0 -0
  47. {mapFolding-0.3.8.dist-info → mapFolding-0.3.10.dist-info}/WHEEL +0 -0
  48. {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 EnumIndices, relativePathSyntheticModules, setDatatypeElephino, setDatatypeFoldsTotal, setDatatypeLeavesTotal, setDatatypeModule
2
- from mapFolding import indexMy, indexTrack, getAlgorithmSource, ParametersNumba, parametersNumbaDEFAULT, hackSSOTdatatype, hackSSOTdtype
3
- from typing import cast, Dict, List, Optional, Sequence, Set, Type, Union
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, callNode: ast.Call) -> ast.AST:
57
- callNodeVisited = self.generic_visit(callNode)
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, parallel: bool=False) -> 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
- # TODO: more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
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
- astArgsNumbaSignature = ast.Tuple(elts=listNumbaParameterSignature, ctx=ast.Load())
173
-
174
- if astCallable.name == 'countInitialize':
175
- parametersNumba = {}
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
- parametersNumba = parametersNumbaDEFAULT if not parallel else ParametersNumba({**parametersNumbaDEFAULT, 'parallel': True})
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=[astArgsNumbaSignature], keywords=listKeywordsNumbaSignature)
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
- parallel = callableTarget == 'countParallel'
330
- callableDecorated = decorateCallableWithNumba(callableInlined, parallel)
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
- class AppendDunderInit(ast.NodeTransformer):
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
- Parameters:
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
- Returns:
407
- List[Tuple[pathlib.Path, str]]: List of tuples containing:
408
- - Generated file paths
409
- - Associated callable names
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
- Raises:
412
- Exception: If inline operation fails during code generation.
420
+ astSource = ast.parse(codeSource)
413
421
 
414
- Note:
415
- - Generated files are placed in a synthetic modules subdirectory
416
- - Modifies __init__.py files to expose generated modules
417
- - Current implementation contains hardcoded paths that should be abstracted
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
- listPathFilenamesDestination: list[tuple[pathlib.Path, str]] = []
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
- # TODO abstract this process
425
- # especially remove the hardcoded paths and filenames
498
+ pathFilename = getPathFilenameWrite(callableTarget)
499
+ astImport = makeAstImport(callableTarget)
426
500
 
427
- for callableTarget in listCallablesAsStr:
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 = inlineOneCallable(codeSource, callableTarget)
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
- # This almost works: it duplicates existing imports, though
438
- listTuplesDunderInit = AppendDunderInit(listPathFilenamesDestination).process_init_files()
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
- inlineMapFoldingNumba(listCallablesAsStr)
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
- from numpy import integer
4
- from mapFolding import indexMy, indexTrack
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: numpy.ndarray[Tuple[int, int, int], numpy.dtype[integer[Any]]]
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 mapFolding import indexMy, indexTrack
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=False, inline='never', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=True)
8
- def countParallel(connectionGraph: numpy.ndarray[Tuple[int, int, int], numpy.dtype[integer[Any]]], foldGroups: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], gapsWhere: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], my: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], track: numpy.ndarray[Tuple[int, int], numpy.dtype[integer[Any]]]):
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 mapFolding import indexMy, indexTrack
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=False, inline='never', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=False)
8
- def countSequential(connectionGraph: numpy.ndarray[Tuple[int, int, int], numpy.dtype[integer[Any]]], foldGroups: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], gapsWhere: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], my: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], track: numpy.ndarray[Tuple[int, int], numpy.dtype[integer[Any]]]):
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)