Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/misc/func_persist.py
4045 views
1
r"""
2
Support for persistent functions in .sage files
3
4
Persistent functions are functions whose values are stored on disk
5
so they do not have to be recomputed.
6
7
The inputs to the function must be hashable (so lists are not
8
allowed). Though a hash is used, in the incredibly unlikely event
9
that a hash collision occurs, your function will not return an
10
incorrect result because of this (though the cache might not be
11
used either).
12
13
This is meant to be used from ``.sage`` files, not from
14
library ``.py`` files.
15
16
To use this disk caching mechanism, just put
17
``@func_persist`` right before your function
18
definition. For example,
19
20
::
21
22
@func_persist
23
def bern(n):
24
"Return the n-th Bernoulli number, caching the result to disk."
25
return bernoulli(n)
26
27
You can then use the function ``bern`` as usual, except
28
it will almost instantly return values that have already been
29
computed, even if you quit and restart.
30
31
The disk cache files are stored by default in the subdirectory
32
``func_persist`` of the current working directory,
33
with one file for each evaluation of the function.
34
"""
35
36
########################################################################
37
# Copyright (C) 2006 William Stein <[email protected]>
38
#
39
# Distributed under the terms of the GNU General Public License (GPL)
40
#
41
# http://www.gnu.org/licenses/
42
########################################################################
43
44
import inspect, os
45
46
import persist
47
48
class func_persist:
49
r"""
50
Put ``@func_persist`` right before your function
51
definition to cache values it computes to disk.
52
"""
53
def __init__(self, f, dir='func_persist'):
54
from sage.misc.misc import sage_makedirs
55
self.__func = f
56
self.__dir = dir
57
sage_makedirs(dir)
58
self.__doc__ = '%s%s%s'%(\
59
f.func_name,
60
inspect.formatargspec(*inspect.getargs(f.func_code)),
61
f.__doc__)
62
63
def __call__(self, *args, **kwds):
64
key = (tuple(args), tuple(kwds.items()))
65
h = hash(key)
66
name = '%s/%s_%s.sobj'%(self.__dir, self.__func.func_name, h)
67
68
if os.path.exists(name):
69
key2, val = persist.load(name)
70
if key == key2:
71
# We save and test equality of keys to avoid
72
# the (extremely remote) possibility of a hash
73
# collision. Correctness is crucial in mathematics.
74
return val
75
76
val = self.__func(*args, **kwds)
77
persist.save((key, val), name)
78
return val
79
80
81
82
83
84