Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

r""" 

Support for persistent functions in .sage files 

 

Persistent functions are functions whose values are stored on disk 

so they do not have to be recomputed. 

 

The inputs to the function must be hashable (so lists are not 

allowed). Though a hash is used, in the incredibly unlikely event 

that a hash collision occurs, your function will not return an 

incorrect result because of this (though the cache might not be 

used either). 

 

This is meant to be used from ``.sage`` files, not from 

library ``.py`` files. 

 

To use this disk caching mechanism, just put 

``@func_persist`` right before your function 

definition. For example, 

 

:: 

 

@func_persist 

def bern(n): 

"Return the n-th Bernoulli number, caching the result to disk." 

return bernoulli(n) 

 

You can then use the function ``bern`` as usual, except 

it will almost instantly return values that have already been 

computed, even if you quit and restart. 

 

The disk cache files are stored by default in the subdirectory 

``func_persist`` of the current working directory, 

with one file for each evaluation of the function. 

""" 

from __future__ import absolute_import 

 

######################################################################## 

# Copyright (C) 2006 William Stein <wstein@gmail.com> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# 

# http://www.gnu.org/licenses/ 

######################################################################## 

 

import inspect, os 

 

from . import persist 

 

class func_persist: 

r""" 

Put ``@func_persist`` right before your function 

definition to cache values it computes to disk. 

""" 

def __init__(self, f, dir='func_persist'): 

from sage.misc.misc import sage_makedirs 

self.__func = f 

self.__dir = dir 

sage_makedirs(dir) 

self.__doc__ = '%s%s%s'%(\ 

f.__name__, 

inspect.formatargspec(*inspect.getargs(f.__code__)), 

f.__doc__) 

 

def __call__(self, *args, **kwds): 

key = (tuple(args), tuple(kwds.items())) 

h = hash(key) 

name = '%s/%s_%s.sobj'%(self.__dir, self.__func.__name__, h) 

 

if os.path.exists(name): 

key2, val = persist.load(name) 

if key == key2: 

# We save and test equality of keys to avoid 

# the (extremely remote) possibility of a hash 

# collision. Correctness is crucial in mathematics. 

return val 

 

val = self.__func(*args, **kwds) 

persist.save((key, val), name) 

return val