mapFolding 0.3.2__py3-none-any.whl → 0.3.4__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.
@@ -0,0 +1,67 @@
1
+ from cffconvert.cli.create_citation import create_citation
2
+ from typing import Any, Dict
3
+ import cffconvert
4
+ import pathlib
5
+ import tomli
6
+ import inspect
7
+ import json
8
+
9
+ """
10
+ Tentative plan:
11
+ - Commit and push to GitHub
12
+ - GitHub Action gathers information from the sources of truth
13
+ - If the citation needs to be updated, write to both
14
+ - pathFilenameCitationSSOT
15
+ - pathFilenameCitationDOTcffRepo
16
+ - Commit and push to GitHub
17
+ - this complicates things
18
+ - I want the updated citation to be in the `commit` field of itself
19
+ """
20
+
21
+ """cffconvert.Citation fields and the source of truth
22
+ abstract: pathFilenameCitationSSOT
23
+ authors: pathFilenamePackageSSOT
24
+ cff-version: pathFilenameCitationSSOT
25
+ commit: workflows['Make GitHub Release']
26
+ contact: pathFilenamePackageSSOT
27
+ date-released: workflows['Make GitHub Release']
28
+ doi: pathFilenameCitationSSOT
29
+ identifiers: workflows['Make GitHub Release']
30
+ keywords: pathFilenamePackageSSOT
31
+ license: pathFilenamePackageSSOT
32
+ license-url: pathFilenamePackageSSOT
33
+ message: pathFilenameCitationSSOT
34
+ preferred-citation: pathFilenameCitationSSOT
35
+ references: to be determined
36
+ repository: pathFilenamePackageSSOT
37
+ repository-artifact: (https://pypi.org/pypi/{package_name}/json').json()['releases']
38
+ repository-code: workflows['Make GitHub Release']
39
+ title: pathFilenamePackageSSOT
40
+ type: pathFilenameCitationSSOT
41
+ url: pathFilenamePackageSSOT
42
+ version: pathFilenamePackageSSOT
43
+ """
44
+ # Prefer reliable, dynamic values over hardcoded ones
45
+ packageName: str = 'mapFolding'
46
+ pathRepoRoot = pathlib.Path(__file__).parent.parent.parent
47
+ pathFilenamePackageSSOT = pathRepoRoot / 'pyproject.toml'
48
+
49
+ filenameGitHubAction = 'updateCitation.yml'
50
+ pathFilenameGitHubAction = pathRepoRoot / '.github' / 'workflows' / filenameGitHubAction
51
+
52
+ filenameCitationDOTcff = 'CITATION.cff'
53
+ pathCitations = pathRepoRoot / packageName / 'citations'
54
+ pathFilenameCitationSSOT = pathCitations / filenameCitationDOTcff
55
+ pathFilenameCitationDOTcffRepo = pathRepoRoot / filenameCitationDOTcff
56
+
57
+ tomlPackageData: Dict[str, Any] = tomli.loads(pathFilenamePackageSSOT.read_text())['project']
58
+
59
+ citationObject: cffconvert.Citation = create_citation(infile=pathFilenameCitationSSOT, url=None)
60
+
61
+ path_cffconvert = pathlib.Path(inspect.getfile(cffconvert)).parent
62
+ pathFilenameSchema = path_cffconvert / "schemas/1.2.0/schema.json"
63
+ scheme: Dict[str, Any] = json.loads(pathFilenameSchema.read_text())
64
+ schemaSpecifications: Dict[str, Any] = scheme['properties']
65
+
66
+ for property, subProperties in schemaSpecifications.items():
67
+ print(property, subProperties.get('items', None))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mapFolding
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Count distinct ways to fold a map (or a strip of stamps)
5
5
  Author-email: Hunter Hogan <HunterHogan@pm.me>
6
6
  License: CC-BY-NC-4.0
@@ -29,12 +29,14 @@ Requires-Dist: jupyter; extra == "benchmark"
29
29
  Requires-Dist: pandas; extra == "benchmark"
30
30
  Requires-Dist: tqdm; extra == "benchmark"
31
31
  Provides-Extra: testing
32
+ Requires-Dist: cffconvert; extra == "testing"
32
33
  Requires-Dist: more_itertools; extra == "testing"
33
34
  Requires-Dist: pytest; extra == "testing"
34
35
  Requires-Dist: pytest-cov; extra == "testing"
35
36
  Requires-Dist: pytest-env; extra == "testing"
36
37
  Requires-Dist: pytest-xdist; extra == "testing"
37
38
  Requires-Dist: python_minifier; extra == "testing"
39
+ Requires-Dist: tomli; extra == "testing"
38
40
 
39
41
  # Algorithm(s) for counting distinct ways to fold a map (or a strip of stamps)
40
42
 
@@ -52,7 +54,7 @@ The directory [mapFolding/reference](https://github.com/hunterhogan/mapFolding/b
52
54
  - [hunterNumba.py](https://github.com/hunterhogan/mapFolding/blob/main/mapFolding/reference), a one-size-fits-all, self-contained, reasonably fast, contemporary algorithm that is nevertheless infected by _noobaceae ignorancium_, and
53
55
  - miscellaneous notes.
54
56
 
55
- [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/unittests.yml) [![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e)](https://youtu.be/g6f_miE91mk&t=4) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
57
+ [![pip install mapFolding](https://img.shields.io/badge/pip%20install-mapFolding-gray.svg?colorB=3b434b)](https://pypi.org/project/mapFolding/) [![Python Tests](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml/badge.svg)](https://github.com/hunterhogan/mapFolding/actions/workflows/pythonTests.yml) [![Static Badge](https://img.shields.io/badge/stinkin'%20badges-don't%20need-b98e5e)](https://youtu.be/g6f_miE91mk&t=4) ![PyPI - Downloads](https://img.shields.io/pypi/dd/mapFolding) ![Static Badge](https://img.shields.io/badge/issues-I%20have%20them-brightgreen) ![GitHub repo size](https://img.shields.io/github/repo-size/hunterhogan/mapFolding)
56
58
 
57
59
  ## Simple, easy usage based on OEIS IDs
58
60
 
@@ -0,0 +1,26 @@
1
+ benchmarks/benchmarking.py,sha256=HD_0NSvuabblg94ftDre6LFnXShTe8MYj3hIodW-zV0,3076
2
+ citations/updateCitation.py,sha256=3AUPo9_4SfH8AwQBMRl7KygAXoMRjQSqFl3ERWxtrtk,2541
3
+ reference/flattened.py,sha256=6blZ2Y9G8mu1F3gV8SKndPE398t2VVFlsgKlyeJ765A,16538
4
+ reference/hunterNumba.py,sha256=HWndRgsajOf76rbb2LDNEZ6itsdYbyV-k3wgOFjeR6c,7104
5
+ reference/irvineJavaPort.py,sha256=Sj-63Z-OsGuDoEBXuxyjRrNmmyl0d7Yz_XuY7I47Oyg,4250
6
+ reference/jax.py,sha256=rojyK80lOATtbzxjGOHWHZngQa47CXCLJHZwIdN2MwI,14955
7
+ reference/lunnan.py,sha256=XEcql_gxvCCghb6Or3qwmPbn4IZUbZTaSmw_fUjRxZE,5037
8
+ reference/lunnanNumpy.py,sha256=HqDgSwTOZA-G0oophOEfc4zs25Mv4yw2aoF1v8miOLk,4653
9
+ reference/lunnanWhile.py,sha256=7NY2IKO5XBgol0aWWF_Fi-7oTL9pvu_z6lB0TF1uVHk,4063
10
+ reference/rotatedEntryPoint.py,sha256=z0QyDQtnMvXNj5ntWzzJUQUMFm1-xHGLVhtYzwmczUI,11530
11
+ reference/total_countPlus1vsPlusN.py,sha256=usenM8Yn_G1dqlPl7NKKkcnbohBZVZBXTQRm2S3_EDA,8106
12
+ someAssemblyRequired/__init__.py,sha256=7iODZE6dM4h52spgivUvAuVsvYdSx-_YcSTz1gX82Vw,89
13
+ someAssemblyRequired/generalizeSourceCode.py,sha256=qyJD0ZdG0t-SYTItL_JjaIXm3-joWt3e-2nMSAH4Dbg,6392
14
+ someAssemblyRequired/getLLVMforNoReason.py,sha256=FtJzw2pZS3A4NimWdZsegXaU-vKeCw8m67kcfb5wvGM,894
15
+ someAssemblyRequired/makeJob.py,sha256=iaLjr-FhFloTF6wSuwOpurgpqJulZht9CxNo9MDidbg,949
16
+ someAssemblyRequired/synthesizeModuleJob.py,sha256=xLak-ZZ1zQ92jBobhJqbnA1Fua9ofiRvLdK1fmD8s_s,7271
17
+ someAssemblyRequired/synthesizeModules.py,sha256=JGOx69DGCcCntRtw7aOXXcmERCHqVyhFo1oiKh3P8Mg,8842
18
+ syntheticModules/__init__.py,sha256=nDtS5UFMKN-F5pTp0qKA0J0I-XR3n3OFxV2bosieBu8,131
19
+ syntheticModules/countInitialize.py,sha256=QqKfQxCmUJuJutNxOZ0VfqYEHnuk7XSkCYx7RKz3kn4,4239
20
+ syntheticModules/countParallel.py,sha256=77JzO3TsccjSUJRExZ0Nxdqowd_Sm0_2bRziVx5XMI4,5355
21
+ syntheticModules/countSequential.py,sha256=QixgcN9R5zcrmJjxSO4oOCYViWogA35HbDNlni9hw8o,3655
22
+ mapFolding-0.3.4.dist-info/METADATA,sha256=v8MJLZBzqS2hBp4trsRjjLzn8RAsddUPg16IiI9J1cg,7617
23
+ mapFolding-0.3.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
24
+ mapFolding-0.3.4.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
25
+ mapFolding-0.3.4.dist-info/top_level.txt,sha256=yVG9dNZywoaddcsUdEDg7o0XOBzJd_4Z-sDaXGHpiMY,69
26
+ mapFolding-0.3.4.dist-info/RECORD,,
@@ -1,3 +1,5 @@
1
1
  benchmarks
2
+ citations
2
3
  reference
3
4
  someAssemblyRequired
5
+ syntheticModules
@@ -1,3 +1,2 @@
1
- from .countSequential import countSequential
2
- from .countParallel import countParallel
3
- from .countInitialize import countInitialize
1
+ from .makeJob import makeStateJob
2
+ # from .generalizeSourceCode import makeInlineFunction
@@ -0,0 +1,122 @@
1
+ from mapFolding import datatypeLargeDEFAULT, datatypeMediumDEFAULT, datatypeSmallDEFAULT
2
+ from typing import Dict, Optional, List, Set, Union
3
+ import ast
4
+
5
+ class RecursiveInlinerWithEnum(ast.NodeTransformer):
6
+ """Process AST nodes to inline functions and substitute enum values.
7
+ Also handles function decorators during inlining."""
8
+
9
+ def __init__(self, dictionaryFunctions: Dict[str, ast.FunctionDef], dictionaryEnumValues: Dict[str, int]) -> None:
10
+ self.dictionaryFunctions = dictionaryFunctions
11
+ self.dictionaryEnumValues = dictionaryEnumValues
12
+ self.processed = set()
13
+
14
+ def inlineFunctionBody(self, functionName: str) -> Optional[ast.FunctionDef]:
15
+ if functionName in self.processed:
16
+ return None
17
+
18
+ self.processed.add(functionName)
19
+ inlineDefinition = self.dictionaryFunctions[functionName]
20
+ # Recursively process the function body
21
+ for node in ast.walk(inlineDefinition):
22
+ self.visit(node)
23
+ return inlineDefinition
24
+
25
+ def visit_Attribute(self, node: ast.Attribute) -> ast.AST:
26
+ # Substitute enum identifiers (e.g., indexMy.leaf1ndex.value)
27
+ if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name):
28
+ enumPath = f"{node.value.value.id}.{node.value.attr}.{node.attr}"
29
+ if enumPath in self.dictionaryEnumValues:
30
+ return ast.Constant(value=self.dictionaryEnumValues[enumPath])
31
+ return self.generic_visit(node)
32
+
33
+ def visit_Call(self, node: ast.Call) -> ast.AST:
34
+ callNode = self.generic_visit(node)
35
+ if isinstance(callNode, ast.Call) and isinstance(callNode.func, ast.Name) and callNode.func.id in self.dictionaryFunctions:
36
+ inlineDefinition = self.inlineFunctionBody(callNode.func.id)
37
+ if (inlineDefinition and inlineDefinition.body):
38
+ lastStmt = inlineDefinition.body[-1]
39
+ if isinstance(lastStmt, ast.Return) and lastStmt.value is not None:
40
+ return self.visit(lastStmt.value)
41
+ elif isinstance(lastStmt, ast.Expr) and lastStmt.value is not None:
42
+ return self.visit(lastStmt.value)
43
+ return ast.Constant(value=None)
44
+ return callNode
45
+
46
+ def visit_Expr(self, node: ast.Expr) -> Union[ast.AST, List[ast.AST]]:
47
+ if isinstance(node.value, ast.Call):
48
+ if isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions:
49
+ inlineDefinition = self.inlineFunctionBody(node.value.func.id)
50
+ if inlineDefinition:
51
+ return [self.visit(stmt) for stmt in inlineDefinition.body]
52
+ return self.generic_visit(node)
53
+
54
+ def findRequiredImports(node: ast.AST) -> Set[str]:
55
+ """Find all modules that need to be imported based on AST analysis.
56
+ NOTE: due to hardcoding, this is a glorified regex. No, wait, this is less versatile than regex."""
57
+ requiredImports = set()
58
+
59
+ class ImportFinder(ast.NodeVisitor):
60
+ def visit_Name(self, node: ast.Name) -> None:
61
+ if node.id in {'numba'}:
62
+ requiredImports.add(node.id)
63
+ self.generic_visit(node)
64
+
65
+ def visitDecorator(self, node: ast.AST) -> None:
66
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
67
+ if node.func.id == 'jit':
68
+ requiredImports.add('numba')
69
+ self.generic_visit(node)
70
+
71
+ ImportFinder().visit(node)
72
+ return requiredImports
73
+
74
+ def generateImports(requiredImports: Set[str]) -> str:
75
+ """Generate import statements based on required modules."""
76
+ importStatements = {'import numba', 'from mapFolding import indexMy, indexTrack'}
77
+
78
+ importMapping = {
79
+ 'numba': 'import numba',
80
+ }
81
+
82
+ for moduleName in sorted(requiredImports):
83
+ if moduleName in importMapping:
84
+ importStatements.add(importMapping[moduleName])
85
+
86
+ return '\n'.join(importStatements)
87
+
88
+ def makeInlineFunction(sourceCode: str, targetFunctionName: str, dictionaryEnumValues: Dict[str, int], skipEnum: bool=False, **keywordArguments: Optional[str]):
89
+ datatypeLarge = keywordArguments.get('datatypeLarge', datatypeLargeDEFAULT)
90
+ datatypeMedium = keywordArguments.get('datatypeMedium', datatypeMediumDEFAULT)
91
+ datatypeSmall = keywordArguments.get('datatypeSmall', datatypeSmallDEFAULT)
92
+ if skipEnum:
93
+ dictionaryEnumValues = {}
94
+ dictionaryParsed = ast.parse(sourceCode)
95
+ dictionaryFunctions = {
96
+ element.name: element
97
+ for element in dictionaryParsed.body
98
+ if isinstance(element, ast.FunctionDef)
99
+ }
100
+ nodeTarget = dictionaryFunctions[targetFunctionName]
101
+ nodeInliner = RecursiveInlinerWithEnum(dictionaryFunctions, dictionaryEnumValues)
102
+ nodeInlined = nodeInliner.visit(nodeTarget)
103
+ ast.fix_missing_locations(nodeInlined)
104
+ callableInlinedDecorators = [decorator for decorator in nodeInlined.decorator_list]
105
+
106
+ requiredImports = findRequiredImports(nodeInlined)
107
+ importStatements = generateImports(requiredImports)
108
+ importsRequired = importStatements
109
+ dictionaryDecoratorsNumba={
110
+ 'countInitialize':
111
+ f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
112
+ 'countParallel':
113
+ f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeLarge}[::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=True, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
114
+ 'countSequential':
115
+ f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeLarge}[::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
116
+ }
117
+
118
+ lineNumbaDecorator = dictionaryDecoratorsNumba[targetFunctionName]
119
+
120
+ # inlinedCode = ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
121
+ callableInlined = lineNumbaDecorator + ast.unparse(nodeInlined)
122
+ return (callableInlined, callableInlinedDecorators, importsRequired)
@@ -0,0 +1,21 @@
1
+ from mapFolding import getPathFilenameFoldsTotal
2
+ from mapFolding import outfitCountFolds
3
+ from typing import Any, Optional, Sequence, Type
4
+ import pathlib
5
+ import pickle
6
+
7
+ def makeStateJob(listDimensions: Sequence[int], **keywordArguments: Optional[Type[Any]]) -> pathlib.Path:
8
+
9
+ stateUniversal = outfitCountFolds(listDimensions, computationDivisions=None, CPUlimit=None, **keywordArguments)
10
+
11
+ from syntheticModules import countInitialize
12
+ countInitialize(stateUniversal['connectionGraph'], stateUniversal['gapsWhere'], stateUniversal['my'], stateUniversal['track'])
13
+
14
+ pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal['mapShape'])
15
+ suffix = pathFilenameChopChop.suffix
16
+ pathJob = pathlib.Path(str(pathFilenameChopChop)[0:-len(suffix)])
17
+ pathJob.mkdir(parents=True, exist_ok=True)
18
+ pathFilenameJob = pathJob / 'stateJob.pkl'
19
+
20
+ pathFilenameJob.write_bytes(pickle.dumps(stateUniversal))
21
+ return pathFilenameJob
@@ -1,10 +1,12 @@
1
- from mapFolding import getPathFilenameFoldsTotal, dtypeNumpyDefaults, thisSeemsVeryComplicated
2
- from mapFolding import make_dtype, datatypeLarge, dtypeLarge, datatypeMedium, dtypeMedium, datatypeSmall, dtypeSmall
3
- from mapFolding import outfitCountFolds, computationState, indexMy, indexTrack
4
- from someAssemblyRequired import countInitialize, countSequential
5
- from typing import Any, Optional, Sequence, Type
1
+ from mapFolding import getPathFilenameFoldsTotal
2
+ from mapFolding import make_dtype, datatypeLargeDEFAULT, datatypeMediumDEFAULT, datatypeSmallDEFAULT, datatypeModuleDEFAULT
3
+ from mapFolding import computationState
4
+ from someAssemblyRequired import makeStateJob
5
+ from typing import Optional
6
6
  import more_itertools
7
7
  import inspect
8
+ import importlib
9
+ import importlib.util
8
10
  import numpy
9
11
  import pathlib
10
12
  import pickle
@@ -12,20 +14,7 @@ import python_minifier
12
14
 
13
15
  identifierCallableLaunch = "goGoGadgetAbsurdity"
14
16
 
15
- def makeStateJob(listDimensions: Sequence[int], **keywordArguments: Optional[Type[Any]]):
16
- stateUniversal = outfitCountFolds(listDimensions, computationDivisions=None, CPUlimit=None, **keywordArguments)
17
- countInitialize(stateUniversal['connectionGraph'], stateUniversal['gapsWhere'], stateUniversal['my'], stateUniversal['track'])
18
-
19
- pathFilenameChopChop = getPathFilenameFoldsTotal(stateUniversal['mapShape'])
20
- suffix = pathFilenameChopChop.suffix
21
- pathJob = pathlib.Path(str(pathFilenameChopChop)[0:-len(suffix)])
22
- pathJob.mkdir(parents=True, exist_ok=True)
23
- pathFilenameJob = pathJob / 'stateJob.pkl'
24
-
25
- pathFilenameJob.write_bytes(pickle.dumps(stateUniversal))
26
- return pathFilenameJob
27
-
28
- def convertNDArrayToStr(arrayTarget: numpy.ndarray, identifierName: str) -> str:
17
+ def makeStrRLEcompacted(arrayTarget: numpy.ndarray, identifierName: str) -> str:
29
18
  def process_nested_array(arraySlice):
30
19
  if isinstance(arraySlice, numpy.ndarray) and arraySlice.ndim > 1:
31
20
  return [process_nested_array(arraySlice[index]) for index in range(arraySlice.shape[0])]
@@ -54,22 +43,25 @@ def convertNDArrayToStr(arrayTarget: numpy.ndarray, identifierName: str) -> str:
54
43
  return f"{identifierName} = numpy.array({stringMinimized}, dtype=numpy.{arrayTarget.dtype})"
55
44
 
56
45
  def writeModuleWithNumba(listDimensions, **keywordArguments: Optional[str]) -> pathlib.Path:
57
- datatypeLargeAsStr = keywordArguments.get('datatypeLarge', thisSeemsVeryComplicated.datatypeLarge)
58
- datatypeMediumAsStr = keywordArguments.get('datatypeMedium', thisSeemsVeryComplicated.datatypeMedium)
59
- datatypeSmallAsStr = keywordArguments.get('datatypeSmall', thisSeemsVeryComplicated.datatypeSmall)
46
+ datatypeLarge = keywordArguments.get('datatypeLarge', datatypeLargeDEFAULT)
47
+ datatypeMedium = keywordArguments.get('datatypeMedium', datatypeMediumDEFAULT)
48
+ datatypeSmall = keywordArguments.get('datatypeSmall', datatypeSmallDEFAULT)
49
+ datatypeModule = keywordArguments.get('datatypeModule', datatypeModuleDEFAULT)
60
50
 
61
- numpy_dtypeLarge = make_dtype(datatypeLargeAsStr) # type: ignore
62
- numpy_dtypeMedium = make_dtype(datatypeMediumAsStr) # type: ignore
63
- numpy_dtypeSmall = make_dtype(datatypeSmallAsStr) # type: ignore
51
+ dtypeLarge = make_dtype(datatypeLarge, datatypeModule) # type: ignore
52
+ dtypeMedium = make_dtype(datatypeMedium, datatypeModule) # type: ignore
53
+ dtypeSmall = make_dtype(datatypeSmall, datatypeModule) # type: ignore
64
54
 
65
- pathFilenameJob = makeStateJob(listDimensions, dtypeLarge = numpy_dtypeLarge, dtypeMedium = numpy_dtypeMedium, dtypeSmall = numpy_dtypeSmall)
55
+ pathFilenameJob = makeStateJob(listDimensions, dtypeLarge = dtypeLarge, dtypeMedium = dtypeMedium, dtypeSmall = dtypeSmall)
66
56
  stateJob: computationState = pickle.loads(pathFilenameJob.read_bytes())
67
57
  pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateJob['mapShape'], pathFilenameJob.parent)
68
58
 
69
- codeSource = inspect.getsource(countSequential)
59
+ from syntheticModules import countSequential
60
+ algorithmSource = countSequential
61
+ codeSource = inspect.getsource(algorithmSource)
70
62
 
71
63
  # forceinline=True might actually be useful
72
- parametersNumba = f"numba.types.{datatypeLargeAsStr}(), \
64
+ parametersNumba = f"numba.types.{datatypeLarge}(), \
73
65
  cache=True, \
74
66
  nopython=True, \
75
67
  fastmath=True, \
@@ -96,14 +88,14 @@ no_cpython_wrapper=False, \
96
88
  ImaIndent = ' '
97
89
  linesDataDynamic = """"""
98
90
  linesDataDynamic = "\n".join([linesDataDynamic
99
- , ImaIndent + f"foldsTotal = numba.types.{datatypeLargeAsStr}(0)"
100
- , ImaIndent + convertNDArrayToStr(stateJob['foldGroups'], 'foldGroups')
101
- , ImaIndent + convertNDArrayToStr(stateJob['gapsWhere'], 'gapsWhere')
91
+ , ImaIndent + f"foldsTotal = numba.types.{datatypeLarge}(0)"
92
+ , ImaIndent + makeStrRLEcompacted(stateJob['foldGroups'], 'foldGroups')
93
+ , ImaIndent + makeStrRLEcompacted(stateJob['gapsWhere'], 'gapsWhere')
102
94
  ])
103
95
 
104
96
  linesDataStatic = """"""
105
97
  linesDataStatic = "\n".join([linesDataStatic
106
- , ImaIndent + convertNDArrayToStr(stateJob['connectionGraph'], 'connectionGraph')
98
+ , ImaIndent + makeStrRLEcompacted(stateJob['connectionGraph'], 'connectionGraph')
107
99
  ])
108
100
 
109
101
  my = stateJob['my']
@@ -127,7 +119,7 @@ no_cpython_wrapper=False, \
127
119
  elif 'track[indexTrack.' in lineSource:
128
120
  # leafAbove = track[indexTrack.leafAbove.value]
129
121
  identifier, statement = lineSource.split('=')
130
- lineSource = ImaIndent + convertNDArrayToStr(eval(statement.strip()), identifier.strip())
122
+ lineSource = ImaIndent + makeStrRLEcompacted(eval(statement.strip()), identifier.strip())
131
123
 
132
124
  linesAlgorithm = "\n".join([linesAlgorithm
133
125
  , lineSource
@@ -163,8 +155,16 @@ if __name__ == '__main__':
163
155
  return pathFilenameDestination
164
156
 
165
157
  if __name__ == '__main__':
166
- listDimensions = [3,15]
158
+ listDimensions = [6,6]
167
159
  datatypeLarge = 'int64'
168
160
  datatypeMedium = 'uint8'
169
161
  datatypeSmall = datatypeMedium
170
- writeModuleWithNumba(listDimensions, datatypeLarge=datatypeLarge, datatypeMedium=datatypeMedium, datatypeSmall=datatypeSmall)
162
+ pathFilenameModule = writeModuleWithNumba(listDimensions, datatypeLarge=datatypeLarge, datatypeMedium=datatypeMedium, datatypeSmall=datatypeSmall)
163
+ # Induce numba.jit compilation
164
+ moduleSpec = importlib.util.spec_from_file_location(pathFilenameModule.stem, pathFilenameModule)
165
+ if moduleSpec is None:
166
+ raise ImportError(f"Could not load module specification from {pathFilenameModule}")
167
+ module = importlib.util.module_from_spec(moduleSpec)
168
+ if moduleSpec.loader is None:
169
+ raise ImportError(f"Could not load module from {moduleSpec}")
170
+ moduleSpec.loader.exec_module(module)
@@ -1,36 +1,20 @@
1
- from mapFolding import indexMy, indexTrack, theDao, datatypeMedium, datatypeLarge, datatypeSmall
2
- import ast
1
+ from mapFolding import indexMy, indexTrack, getAlgorithmSource, ParametersNumba, parametersNumbaDEFAULT, hackSSOTdtype
2
+ from mapFolding import datatypeLargeDEFAULT, datatypeMediumDEFAULT, datatypeSmallDEFAULT
3
3
  import pathlib
4
4
  import inspect
5
+ import numpy
6
+ import numba
7
+ from typing import Dict, Optional, List, Set, Union, Sequence
8
+ import ast
5
9
 
6
- algorithmSource = theDao
7
-
8
- dictionaryDecorators={
9
- 'countInitialize':
10
- f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
11
- 'countParallel':
12
- f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeLarge}[::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=True, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
13
- 'countSequential':
14
- f'@numba.jit((numba.{datatypeSmall}[:,:,::1], numba.{datatypeLarge}[::1], numba.{datatypeMedium}[::1], numba.{datatypeSmall}[::1], numba.{datatypeMedium}[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)\n',
15
- }
16
-
17
- def getDictionaryEnumValues():
18
- dictionaryEnumValues = {}
19
- for enumIndex in [indexMy, indexTrack]:
20
- for memberName, memberValue in enumIndex._member_map_.items():
21
- dictionaryEnumValues[f"{enumIndex.__name__}.{memberName}.value"] = memberValue.value
22
- return dictionaryEnumValues
23
-
24
- class RecursiveInlinerWithEnum(ast.NodeTransformer):
25
- """Process AST nodes to inline functions and substitute enum values.
26
- Also handles function decorators during inlining."""
10
+ algorithmSource = getAlgorithmSource()
27
11
 
28
- def __init__(self, dictionaryFunctions, dictionaryEnumValues):
12
+ class RecursiveInliner(ast.NodeTransformer):
13
+ def __init__(self, dictionaryFunctions: Dict[str, ast.FunctionDef]):
29
14
  self.dictionaryFunctions = dictionaryFunctions
30
- self.dictionaryEnumValues = dictionaryEnumValues
31
15
  self.processed = set()
32
16
 
33
- def inlineFunctionBody(self, functionName):
17
+ def inlineFunctionBody(self, functionName: str) -> Optional[ast.FunctionDef]:
34
18
  if functionName in self.processed:
35
19
  return None
36
20
 
@@ -41,15 +25,7 @@ class RecursiveInlinerWithEnum(ast.NodeTransformer):
41
25
  self.visit(node)
42
26
  return inlineDefinition
43
27
 
44
- def visit_Attribute(self, node):
45
- # Substitute enum identifiers (e.g., indexMy.leaf1ndex.value)
46
- if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name):
47
- enumPath = f"{node.value.value.id}.{node.value.attr}.{node.attr}"
48
- if enumPath in self.dictionaryEnumValues:
49
- return ast.Constant(value=self.dictionaryEnumValues[enumPath])
50
- return self.generic_visit(node)
51
-
52
- def visit_Call(self, node):
28
+ def visit_Call(self, node: ast.Call) -> ast.AST:
53
29
  callNode = self.generic_visit(node)
54
30
  if isinstance(callNode, ast.Call) and isinstance(callNode.func, ast.Name) and callNode.func.id in self.dictionaryFunctions:
55
31
  inlineDefinition = self.inlineFunctionBody(callNode.func.id)
@@ -59,10 +35,10 @@ class RecursiveInlinerWithEnum(ast.NodeTransformer):
59
35
  return self.visit(lastStmt.value)
60
36
  elif isinstance(lastStmt, ast.Expr) and lastStmt.value is not None:
61
37
  return self.visit(lastStmt.value)
62
- return None
38
+ return ast.Constant(value=None)
63
39
  return callNode
64
40
 
65
- def visit_Expr(self, node):
41
+ def visit_Expr(self, node: ast.Expr) -> Union[ast.AST, List[ast.AST]]:
66
42
  if isinstance(node.value, ast.Call):
67
43
  if isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions:
68
44
  inlineDefinition = self.inlineFunctionBody(node.value.func.id)
@@ -70,62 +46,59 @@ class RecursiveInlinerWithEnum(ast.NodeTransformer):
70
46
  return [self.visit(stmt) for stmt in inlineDefinition.body]
71
47
  return self.generic_visit(node)
72
48
 
73
- def findRequiredImports(node):
74
- """Find all modules that need to be imported based on AST analysis.
75
- NOTE: due to hardcoding, this is a glorified regex. No, wait, this is less versatile than regex."""
76
- requiredImports = set()
49
+ def decorateCallableWithNumba(astCallable: ast.FunctionDef, parallel: bool=False, **keywordArguments: Optional[str]):
50
+ def makeNumbaParameterSignatureElement(signatureElement: ast.arg):
51
+ if isinstance(signatureElement.annotation, ast.Subscript) and isinstance(signatureElement.annotation.slice, ast.Tuple):
77
52
 
78
- class ImportFinder(ast.NodeVisitor):
79
- def visit_Name(self, node):
80
- if node.id in {'numba'}:
81
- requiredImports.add(node.id)
82
- self.generic_visit(node)
53
+ annotationShape = signatureElement.annotation.slice.elts[0]
54
+ if isinstance(annotationShape, ast.Subscript) and isinstance(annotationShape.slice, ast.Tuple):
55
+ shapeAsListSlices = [ast.Slice() for axis in range(len(annotationShape.slice.elts))]
56
+ shapeAsListSlices[-1] = ast.Slice(step=ast.Constant(value=1))
57
+ shapeAST = ast.Tuple(elts=shapeAsListSlices, ctx=ast.Load())
58
+ else:
59
+ shapeAST = ast.Slice(step=ast.Constant(value=1))
83
60
 
84
- def visitDecorator(self, node):
85
- if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
86
- if node.func.id == 'jit':
87
- requiredImports.add('numba')
88
- self.generic_visit(node)
61
+ annotationDtype = signatureElement.annotation.slice.elts[1]
62
+ if isinstance(annotationDtype, ast.Subscript) and isinstance(annotationDtype.slice, ast.Attribute):
63
+ datatypeAST = annotationDtype.slice.attr
64
+ else:
65
+ datatypeAST = None
89
66
 
90
- ImportFinder().visit(node)
91
- return requiredImports
67
+ ndarrayName = signatureElement.arg
68
+ Z0Z_hackyStr = hackSSOTdtype[ndarrayName]
69
+ Z0Z_hackyStr = Z0Z_hackyStr[0] + 'ata' + Z0Z_hackyStr[1:]
70
+ datatype_attr = keywordArguments.get(Z0Z_hackyStr, None) or datatypeAST or eval(Z0Z_hackyStr+'DEFAULT')
92
71
 
93
- def generateImports(requiredImports):
94
- """Generate import statements based on required modules."""
95
- importStatements = {'import numba', 'from mapFolding import indexMy, indexTrack'}
72
+ datatypeNumba = ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr=datatype_attr, ctx=ast.Load())
96
73
 
97
- importMapping = {
98
- 'numba': 'import numba',
99
- }
74
+ return ast.Subscript(value=datatypeNumba, slice=shapeAST, ctx=ast.Load())
100
75
 
101
- for moduleName in sorted(requiredImports):
102
- if moduleName in importMapping:
103
- importStatements.add(importMapping[moduleName])
76
+ # callableSourceDecorators = [decorator for decorator in callableInlined.decorator_list]
104
77
 
105
- return '\n'.join(importStatements)
78
+ listNumbaParameterSignature: List[ast.Subscript] = []
79
+ for parameter in astCallable.args.args:
80
+ signatureElement = makeNumbaParameterSignatureElement(parameter)
81
+ if signatureElement:
82
+ listNumbaParameterSignature.append(signatureElement)
106
83
 
107
- def inlineFunctions(sourceCode, targetFunctionName, dictionaryEnumValues, skipEnum=False):
108
- if skipEnum:
109
- dictionaryEnumValues = {}
110
- dictionaryParsed = ast.parse(sourceCode)
111
- dictionaryFunctions = {
112
- element.name: element
113
- for element in dictionaryParsed.body
114
- if isinstance(element, ast.FunctionDef)
115
- }
116
- nodeTarget = dictionaryFunctions[targetFunctionName]
117
- nodeInliner = RecursiveInlinerWithEnum(dictionaryFunctions, dictionaryEnumValues)
118
- nodeInlined = nodeInliner.visit(nodeTarget)
119
- ast.fix_missing_locations(nodeInlined)
84
+ astArgsNumbaSignature = ast.Tuple(elts=listNumbaParameterSignature, ctx=ast.Load())
85
+
86
+ parametersNumba = parametersNumbaDEFAULT if not parallel else ParametersNumba({**parametersNumbaDEFAULT, 'parallel': True})
87
+ listKeywordsNumbaSignature = [ast.keyword(arg=parameterName, value=ast.Constant(value=parameterValue)) for parameterName, parameterValue in parametersNumba.items()]
120
88
 
121
- requiredImports = findRequiredImports(nodeInlined)
122
- importStatements = generateImports(requiredImports)
89
+ astDecoratorNumba = ast.Call(func=ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr='jit', ctx=ast.Load()), args=[astArgsNumbaSignature], keywords=listKeywordsNumbaSignature)
123
90
 
124
- lineNumbaDecorator = dictionaryDecorators[targetFunctionName]
125
- inlinedCode = importStatements + '\n\n' + lineNumbaDecorator + ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
126
- return inlinedCode
91
+ astCallable.decorator_list = [astDecoratorNumba]
92
+ return astCallable
93
+
94
+ def getDictionaryEnumValues() -> Dict[str, int]:
95
+ dictionaryEnumValues = {}
96
+ for enumIndex in [indexMy, indexTrack]:
97
+ for memberName, memberValue in enumIndex._member_map_.items():
98
+ dictionaryEnumValues[f"{enumIndex.__name__}.{memberName}.value"] = memberValue.value
99
+ return dictionaryEnumValues
127
100
 
128
- def unpackArrays(codeInlined: str, callableTarget: str) -> str:
101
+ def unpackArrays(codeInlined: str) -> str:
129
102
  dictionaryReplaceScalars = {
130
103
  'my[indexMy.dimensionsTotal.value]': 'dimensionsTotal',
131
104
  'my[indexMy.dimensionsUnconstrained.value]': 'dimensionsUnconstrained',
@@ -166,22 +139,32 @@ def unpackArrays(codeInlined: str, callableTarget: str) -> str:
166
139
 
167
140
  return codeInlined
168
141
 
169
- def Z0Z_inlineMapFolding():
142
+ def inlineMapFoldingNumba(**keywordArguments: Optional[str]):
170
143
  dictionaryEnumValues = getDictionaryEnumValues()
171
144
  codeSource = inspect.getsource(algorithmSource)
172
145
  pathFilenameAlgorithm = pathlib.Path(inspect.getfile(algorithmSource))
173
146
 
174
- listCallables = [ 'countInitialize', 'countParallel', 'countSequential', ]
175
-
176
147
  listPathFilenamesDestination: list[pathlib.Path] = []
148
+ listCallables = [ 'countInitialize', 'countParallel', 'countSequential', ]
177
149
  for callableTarget in listCallables:
178
- skipEnum = (callableTarget == 'countInitialize')
179
- skipEnum = (callableTarget == 'countSequential')
180
- pathFilenameDestination = pathFilenameAlgorithm.parent / "someAssemblyRequired" / pathFilenameAlgorithm.with_stem(callableTarget).name
181
- codeInlined = inlineFunctions(codeSource, callableTarget, dictionaryEnumValues, skipEnum)
182
- codeUnpacked = unpackArrays(codeInlined, callableTarget)
183
- pathFilenameDestination.write_text(codeUnpacked)
184
- listPathFilenamesDestination.append(pathFilenameDestination)
150
+ codeParsed: ast.Module = ast.parse(codeSource, type_comments=True)
151
+ codeSourceImportStatements = {statement for statement in codeParsed.body if isinstance(statement, (ast.Import, ast.ImportFrom))}
152
+ dictionaryFunctions = {statement.name: statement for statement in codeParsed.body if isinstance(statement, ast.FunctionDef)}
153
+ callableInlinerWorkhorse = RecursiveInliner(dictionaryFunctions)
154
+ parallel = callableTarget == 'countParallel'
155
+ callableInlined = callableInlinerWorkhorse.inlineFunctionBody(callableTarget)
156
+ if callableInlined:
157
+ ast.fix_missing_locations(callableInlined)
158
+ callableDecorated = decorateCallableWithNumba(callableInlined, parallel, **keywordArguments)
159
+
160
+ importsRequired = "\n".join([ast.unparse(importStatement) for importStatement in codeSourceImportStatements])
161
+ callableInlined = ast.unparse(callableDecorated)
162
+ codeUnpacked = unpackArrays(callableInlined) if callableTarget == 'countSequential' else callableInlined
163
+ # inlinedCode = ast.unparse(ast.Module(body=[nodeInlined], type_ignores=[]))
164
+
165
+ pathFilenameDestination = pathFilenameAlgorithm.parent / "syntheticModules" / pathFilenameAlgorithm.with_stem(callableTarget).name
166
+ pathFilenameDestination.write_text(importsRequired + "\n" + codeUnpacked)
167
+ listPathFilenamesDestination.append(pathFilenameDestination)
185
168
 
186
169
  if __name__ == '__main__':
187
- Z0Z_inlineMapFolding()
170
+ inlineMapFoldingNumba()
@@ -0,0 +1,3 @@
1
+ from .countSequential import countSequential
2
+ from .countParallel import countParallel
3
+ from .countInitialize import countInitialize
@@ -0,0 +1,47 @@
1
+ from numpy import integer
2
+ import numba
3
+ import numpy
4
+ from mapFolding import indexMy, indexTrack
5
+ from typing import Any, Tuple
6
+ @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=False, inline='never', looplift=False, no_cfunc_wrapper=True, no_cpython_wrapper=True, nopython=True, parallel=False)
7
+ def countInitialize(connectionGraph: numpy.ndarray[Tuple[int, int, 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]]]):
8
+ while my[indexMy.leaf1ndex.value] > 0:
9
+ if my[indexMy.leaf1ndex.value] <= 1 or track[indexTrack.leafBelow.value, 0] == 1:
10
+ my[indexMy.dimensionsUnconstrained.value] = my[indexMy.dimensionsTotal.value]
11
+ my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
12
+ my[indexMy.indexDimension.value] = 0
13
+ while my[indexMy.indexDimension.value] < my[indexMy.dimensionsTotal.value]:
14
+ if connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]:
15
+ my[indexMy.dimensionsUnconstrained.value] -= 1
16
+ else:
17
+ my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
18
+ while my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]:
19
+ gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.leafConnectee.value]
20
+ if track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] == 0:
21
+ my[indexMy.gap1ndexCeiling.value] += 1
22
+ track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] += 1
23
+ my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
24
+ my[indexMy.indexDimension.value] += 1
25
+ if not my[indexMy.dimensionsUnconstrained.value]:
26
+ my[indexMy.indexLeaf.value] = 0
27
+ while my[indexMy.indexLeaf.value] < my[indexMy.leaf1ndex.value]:
28
+ gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.indexLeaf.value]
29
+ my[indexMy.gap1ndexCeiling.value] += 1
30
+ my[indexMy.indexLeaf.value] += 1
31
+ my[indexMy.indexMiniGap.value] = my[indexMy.gap1ndex.value]
32
+ while my[indexMy.indexMiniGap.value] < my[indexMy.gap1ndexCeiling.value]:
33
+ gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
34
+ if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == my[indexMy.dimensionsUnconstrained.value]:
35
+ my[indexMy.gap1ndex.value] += 1
36
+ track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
37
+ my[indexMy.indexMiniGap.value] += 1
38
+ if my[indexMy.leaf1ndex.value] > 0:
39
+ my[indexMy.gap1ndex.value] -= 1
40
+ track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]] = gapsWhere[my[indexMy.gap1ndex.value]]
41
+ track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]] = track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]]
42
+ track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
43
+ track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
44
+ track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
45
+ my[indexMy.leaf1ndex.value] += 1
46
+ if my[indexMy.gap1ndex.value] > 0:
47
+ return
@@ -0,0 +1,54 @@
1
+ from numpy import integer
2
+ from typing import Any, Tuple
3
+ import numba
4
+ from mapFolding import indexMy, indexTrack
5
+ import numpy
6
+ @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)
7
+ def countParallel(connectionGraph: numpy.ndarray[Tuple[int, int, int], numpy.dtype[integer[Any]]], foldGroups: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], gapsWherePARALLEL: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], myPARALLEL: numpy.ndarray[Tuple[int], numpy.dtype[integer[Any]]], trackPARALLEL: numpy.ndarray[Tuple[int, int], numpy.dtype[integer[Any]]]):
8
+ for indexSherpa in numba.prange(myPARALLEL[indexMy.taskDivisions.value]):
9
+ gapsWhere = gapsWherePARALLEL.copy()
10
+ my = myPARALLEL.copy()
11
+ my[indexMy.taskIndex.value] = indexSherpa
12
+ track = trackPARALLEL.copy()
13
+ groupsOfFolds: int = 0
14
+ while my[indexMy.leaf1ndex.value] > 0:
15
+ if my[indexMy.leaf1ndex.value] <= 1 or track[indexTrack.leafBelow.value, 0] == 1:
16
+ if my[indexMy.leaf1ndex.value] > foldGroups[-1]:
17
+ groupsOfFolds = groupsOfFolds + 1
18
+ else:
19
+ my[indexMy.dimensionsUnconstrained.value] = my[indexMy.dimensionsTotal.value]
20
+ my[indexMy.gap1ndexCeiling.value] = track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]
21
+ my[indexMy.indexDimension.value] = 0
22
+ while my[indexMy.indexDimension.value] < my[indexMy.dimensionsTotal.value]:
23
+ if connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]] == my[indexMy.leaf1ndex.value]:
24
+ my[indexMy.dimensionsUnconstrained.value] -= 1
25
+ else:
26
+ my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], my[indexMy.leaf1ndex.value]]
27
+ while my[indexMy.leafConnectee.value] != my[indexMy.leaf1ndex.value]:
28
+ if my[indexMy.leaf1ndex.value] != my[indexMy.taskDivisions.value] or my[indexMy.leafConnectee.value] % my[indexMy.taskDivisions.value] == my[indexMy.taskIndex.value]:
29
+ gapsWhere[my[indexMy.gap1ndexCeiling.value]] = my[indexMy.leafConnectee.value]
30
+ if track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] == 0:
31
+ my[indexMy.gap1ndexCeiling.value] += 1
32
+ track[indexTrack.countDimensionsGapped.value, my[indexMy.leafConnectee.value]] += 1
33
+ my[indexMy.leafConnectee.value] = connectionGraph[my[indexMy.indexDimension.value], my[indexMy.leaf1ndex.value], track[indexTrack.leafBelow.value, my[indexMy.leafConnectee.value]]]
34
+ my[indexMy.indexDimension.value] += 1
35
+ my[indexMy.indexMiniGap.value] = my[indexMy.gap1ndex.value]
36
+ while my[indexMy.indexMiniGap.value] < my[indexMy.gap1ndexCeiling.value]:
37
+ gapsWhere[my[indexMy.gap1ndex.value]] = gapsWhere[my[indexMy.indexMiniGap.value]]
38
+ if track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] == my[indexMy.dimensionsUnconstrained.value]:
39
+ my[indexMy.gap1ndex.value] += 1
40
+ track[indexTrack.countDimensionsGapped.value, gapsWhere[my[indexMy.indexMiniGap.value]]] = 0
41
+ my[indexMy.indexMiniGap.value] += 1
42
+ while my[indexMy.leaf1ndex.value] > 0 and my[indexMy.gap1ndex.value] == track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value] - 1]:
43
+ my[indexMy.leaf1ndex.value] -= 1
44
+ track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]
45
+ track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]
46
+ if my[indexMy.leaf1ndex.value] > 0:
47
+ my[indexMy.gap1ndex.value] -= 1
48
+ track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]] = gapsWhere[my[indexMy.gap1ndex.value]]
49
+ track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]] = track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]]
50
+ track[indexTrack.leafBelow.value, track[indexTrack.leafAbove.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
51
+ track[indexTrack.leafAbove.value, track[indexTrack.leafBelow.value, my[indexMy.leaf1ndex.value]]] = my[indexMy.leaf1ndex.value]
52
+ track[indexTrack.gapRangeStart.value, my[indexMy.leaf1ndex.value]] = my[indexMy.gap1ndex.value]
53
+ my[indexMy.leaf1ndex.value] += 1
54
+ foldGroups[my[indexMy.taskIndex.value]] = groupsOfFolds
@@ -1,8 +1,10 @@
1
- from mapFolding import indexMy, indexTrack
1
+ from numpy import integer
2
+ from typing import Any, Tuple
2
3
  import numba
3
-
4
- @numba.jit((numba.uint8[:,:,::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)
5
- def countSequential(connectionGraph, foldGroups, gapsWhere, my, track):
4
+ from mapFolding import indexMy, indexTrack
5
+ import numpy
6
+ @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)
7
+ 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]]]):
6
8
  doFindGaps = True
7
9
  dimensionsTotal = my[indexMy.dimensionsTotal.value]
8
10
  dimensionsUnconstrained = my[indexMy.dimensionsUnconstrained.value]
@@ -1,22 +0,0 @@
1
- benchmarks/benchmarking.py,sha256=HD_0NSvuabblg94ftDre6LFnXShTe8MYj3hIodW-zV0,3076
2
- reference/flattened.py,sha256=6blZ2Y9G8mu1F3gV8SKndPE398t2VVFlsgKlyeJ765A,16538
3
- reference/hunterNumba.py,sha256=HWndRgsajOf76rbb2LDNEZ6itsdYbyV-k3wgOFjeR6c,7104
4
- reference/irvineJavaPort.py,sha256=Sj-63Z-OsGuDoEBXuxyjRrNmmyl0d7Yz_XuY7I47Oyg,4250
5
- reference/jax.py,sha256=rojyK80lOATtbzxjGOHWHZngQa47CXCLJHZwIdN2MwI,14955
6
- reference/lunnan.py,sha256=XEcql_gxvCCghb6Or3qwmPbn4IZUbZTaSmw_fUjRxZE,5037
7
- reference/lunnanNumpy.py,sha256=HqDgSwTOZA-G0oophOEfc4zs25Mv4yw2aoF1v8miOLk,4653
8
- reference/lunnanWhile.py,sha256=7NY2IKO5XBgol0aWWF_Fi-7oTL9pvu_z6lB0TF1uVHk,4063
9
- reference/rotatedEntryPoint.py,sha256=z0QyDQtnMvXNj5ntWzzJUQUMFm1-xHGLVhtYzwmczUI,11530
10
- reference/total_countPlus1vsPlusN.py,sha256=usenM8Yn_G1dqlPl7NKKkcnbohBZVZBXTQRm2S3_EDA,8106
11
- someAssemblyRequired/__init__.py,sha256=nDtS5UFMKN-F5pTp0qKA0J0I-XR3n3OFxV2bosieBu8,131
12
- someAssemblyRequired/countInitialize.py,sha256=hwo9SW_IvB-bgKNfaGvjl40yayFEmZZmeywiEMDSQDw,1840
13
- someAssemblyRequired/countParallel.py,sha256=4MfRYLBA2IBxRiXb04voNcxSDAtmZOe7lrji1c3kFls,2560
14
- someAssemblyRequired/countSequential.py,sha256=8YILeL3rflOhW1ts78ZSgYkPYXMPfusYOPkPtf8Xa3M,3217
15
- someAssemblyRequired/getLLVMforNoReason.py,sha256=FtJzw2pZS3A4NimWdZsegXaU-vKeCw8m67kcfb5wvGM,894
16
- someAssemblyRequired/synthesizeJob.py,sha256=xrcEW-QQPKogYh3O0TaRBSZEd8HgMLtXBTeS0Ps_pns,7500
17
- someAssemblyRequired/synthesizeModules.py,sha256=4mDgzfhm36zIDT8LlcPZzfGfoxRi1Z5rb4rgkAWVtkQ,8625
18
- mapFolding-0.3.2.dist-info/METADATA,sha256=ejEa_RncO5HszEWrbPK7VdUPEvJaufxfQVVsLm46fdA,7526
19
- mapFolding-0.3.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
- mapFolding-0.3.2.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
21
- mapFolding-0.3.2.dist-info/top_level.txt,sha256=yHhQq-bIJhB4pZcof5hXDTIjan0nxcFuOEWb7gy1DuU,42
22
- mapFolding-0.3.2.dist-info/RECORD,,
@@ -1,45 +0,0 @@
1
- from mapFolding import indexMy, indexTrack
2
- import numba
3
-
4
- @numba.jit((numba.uint8[:,:,::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:,::1]), parallel=False, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)
5
- def countInitialize(connectionGraph, gapsWhere, my, track):
6
- while my[7] > 0:
7
- if my[7] <= 1 or track[1, 0] == 1:
8
- my[1] = my[0]
9
- my[3] = track[3, my[7] - 1]
10
- my[4] = 0
11
- while my[4] < my[0]:
12
- if connectionGraph[my[4], my[7], my[7]] == my[7]:
13
- my[1] -= 1
14
- else:
15
- my[8] = connectionGraph[my[4], my[7], my[7]]
16
- while my[8] != my[7]:
17
- gapsWhere[my[3]] = my[8]
18
- if track[2, my[8]] == 0:
19
- my[3] += 1
20
- track[2, my[8]] += 1
21
- my[8] = connectionGraph[my[4], my[7], track[1, my[8]]]
22
- my[4] += 1
23
- if not my[1]:
24
- my[5] = 0
25
- while my[5] < my[7]:
26
- gapsWhere[my[3]] = my[5]
27
- my[3] += 1
28
- my[5] += 1
29
- my[6] = my[2]
30
- while my[6] < my[3]:
31
- gapsWhere[my[2]] = gapsWhere[my[6]]
32
- if track[2, gapsWhere[my[6]]] == my[1]:
33
- my[2] += 1
34
- track[2, gapsWhere[my[6]]] = 0
35
- my[6] += 1
36
- if my[7] > 0:
37
- my[2] -= 1
38
- track[0, my[7]] = gapsWhere[my[2]]
39
- track[1, my[7]] = track[1, track[0, my[7]]]
40
- track[1, track[0, my[7]]] = my[7]
41
- track[0, track[1, my[7]]] = my[7]
42
- track[3, my[7]] = my[2]
43
- my[7] += 1
44
- if my[2] > 0:
45
- return
@@ -1,52 +0,0 @@
1
- from mapFolding import indexMy, indexTrack
2
- import numba
3
-
4
- @numba.jit((numba.uint8[:,:,::1], numba.int64[::1], numba.uint8[::1], numba.uint8[::1], numba.uint8[:,::1]), parallel=True, boundscheck=False, cache=True, error_model="numpy", fastmath=True, looplift=False, nogil=True, nopython=True)
5
- def countParallel(connectionGraph, foldGroups, gapsWherePARALLEL, myPARALLEL, trackPARALLEL):
6
- for indexSherpa in numba.prange(myPARALLEL[9]):
7
- gapsWhere = gapsWherePARALLEL.copy()
8
- my = myPARALLEL.copy()
9
- my[10] = indexSherpa
10
- track = trackPARALLEL.copy()
11
- groupsOfFolds: int = 0
12
- while my[7] > 0:
13
- if my[7] <= 1 or track[1, 0] == 1:
14
- if my[7] > foldGroups[-1]:
15
- groupsOfFolds = groupsOfFolds + 1
16
- else:
17
- my[1] = my[0]
18
- my[3] = track[3, my[7] - 1]
19
- my[4] = 0
20
- while my[4] < my[0]:
21
- if connectionGraph[my[4], my[7], my[7]] == my[7]:
22
- my[1] -= 1
23
- else:
24
- my[8] = connectionGraph[my[4], my[7], my[7]]
25
- while my[8] != my[7]:
26
- if my[7] != my[9] or my[8] % my[9] == my[10]:
27
- gapsWhere[my[3]] = my[8]
28
- if track[2, my[8]] == 0:
29
- my[3] += 1
30
- track[2, my[8]] += 1
31
- my[8] = connectionGraph[my[4], my[7], track[1, my[8]]]
32
- my[4] += 1
33
- my[6] = my[2]
34
- while my[6] < my[3]:
35
- gapsWhere[my[2]] = gapsWhere[my[6]]
36
- if track[2, gapsWhere[my[6]]] == my[1]:
37
- my[2] += 1
38
- track[2, gapsWhere[my[6]]] = 0
39
- my[6] += 1
40
- while my[7] > 0 and my[2] == track[3, my[7] - 1]:
41
- my[7] -= 1
42
- track[1, track[0, my[7]]] = track[1, my[7]]
43
- track[0, track[1, my[7]]] = track[0, my[7]]
44
- if my[7] > 0:
45
- my[2] -= 1
46
- track[0, my[7]] = gapsWhere[my[2]]
47
- track[1, my[7]] = track[1, track[0, my[7]]]
48
- track[1, track[0, my[7]]] = my[7]
49
- track[0, track[1, my[7]]] = my[7]
50
- track[3, my[7]] = my[2]
51
- my[7] += 1
52
- foldGroups[my[10]] = groupsOfFolds