summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorStefan Israelsson Tampe <stefan.itampe@gmail.com>2018-09-02 19:48:52 +0200
committerStefan Israelsson Tampe <stefan.itampe@gmail.com>2018-09-02 19:48:52 +0200
commit0f56fc6181a3167db9f45b8a042a8d2f56ade3a8 (patch)
tree19966c8557ecdd0024903b04157ee90e4af64d4f /modules
parent3d44139af1b65ec71abafec939b5240d3821490b (diff)
refined the errors in the os module, translating scheme errors to python errors. close command changed
Diffstat (limited to 'modules')
-rw-r--r--modules/language/python/compile.scm68
-rw-r--r--modules/language/python/def.scm16
-rw-r--r--modules/language/python/exceptions.scm9
-rw-r--r--modules/language/python/module/_random.scm385
-rw-r--r--modules/language/python/module/io.scm8
-rw-r--r--modules/language/python/module/os.scm15
-rw-r--r--modules/language/python/module/random.py349
-rw-r--r--modules/language/python/module/threading.scm3
-rw-r--r--modules/language/python/string.scm26
-rw-r--r--modules/oop/pf-objects.scm21
10 files changed, 495 insertions, 405 deletions
diff --git a/modules/language/python/compile.scm b/modules/language/python/compile.scm
index 91c33c1..86b30dc 100644
--- a/modules/language/python/compile.scm
+++ b/modules/language/python/compile.scm
@@ -188,7 +188,7 @@
(let ((e (car x)))
(if (pair? e)
(let ((ee (car e)))
- (if (equal? ee 'cons)
+ (if (equal? ee '(@ (guile) cons))
(append (lp (list (cadr e)))
(lp (list (caddr e)))
(lp (cdr x)))
@@ -377,7 +377,7 @@
(union
s
(fold (lambda (x s)
- (match x
+ (match x
((#:test (#:power v2 v1 () . _) . _)
(if v2
(union
@@ -907,6 +907,9 @@
(define lr* (lr `((#:* . ,(mklr (G '*))) (#:/ . ,(mklr (N 'py-/)))
(#:% . ,f%) (#:// . ,(mklr (N 'py-floordiv))))))
+(define lr-or (lr `((#:bor . ,(mklr (N 'py-logior))))))
+(define lr-and (lr `((#:band . ,(mklr (N 'py-logand))))))
+(define lr-xor (lr `((#:bxor . ,(mklr (N 'py-logxor))))))
(define-syntax-rule (gen-table x vs (tag code ...) ...)
(begin
@@ -1016,16 +1019,13 @@
(list '+ (exp vs x))))
(#:band
- ((_ . l)
- (cons (N 'py-logand) (map (g vs exp) l))))
-
+ (x (lr-and vs x)))
+
(#:bxor
- ((_ . l)
- (cons (N 'py-logxor) (map (g vs exp) l))))
+ (x (lr-xor vs x)))
(#:bor
- ((_ . l)
- (cons (N 'py-logior) (map (g vs exp) l))))
+ (x (lr-or vs x)))
(#:not
((_ x)
@@ -1555,18 +1555,18 @@
(,(D 'lam) ,aa
(,(C 'with-return) ,r
,(mk `(,(G 'let) ,(map (lambda (x) (list x #f)) ls)
- (,(C 'with-self) ,c? ,aa
- ,(with-fluids ((return r))
- (wth (exp ns code)))))))))))
+ (,(C 'with-self) ,c? ,aa
+ ,(with-fluids ((return r))
+ (wth (exp ns code)))))))))))
`(set! ,f
(,(C 'def-decor) ,decor
(,(D 'lam) ,aa
(,(C 'with-return) ,r
,(mk `(,(G 'let) ,(map (lambda (x) (list x #f)) ls)
- (,(C 'with-self) ,c? ,aa
- ,(with-fluids ((return r))
- (wth (exp ns code)))))))))))
+ (,(C 'with-self) ,c? ,aa
+ ,(with-fluids ((return r))
+ (wth (exp ns code)))))))))))
(if y?
`(set! ,f
@@ -1575,18 +1575,18 @@
(,(D 'lam) ,aa
(,(C 'with-return) ,r
(,(G 'let) ,(map (lambda (x) (list x #f)) ls)
- (,(C 'with-self) ,c? ,aa
- ,(with-fluids ((return r))
- (mk
- (wth (exp ns code)))))))))))
+ (,(C 'with-self) ,c? ,aa
+ ,(with-fluids ((return r))
+ (mk
+ (wth (exp ns code)))))))))))
`(set! ,f
(,(C 'def-decor) ,decor
(,(D 'lam) ,aa
(,(C 'with-return) ,r
(,(G 'let) ,(map (lambda (x) (list x #f)) ls)
- (,(C 'with-self) ,c? ,aa
- ,(with-fluids ((return r))
- (wth (exp ns code)))))))))))))))
+ (,(C 'with-self) ,c? ,aa
+ ,(with-fluids ((return r))
+ (wth (exp ns code)))))))))))))))
(#:global
((_ . _)
@@ -1871,7 +1871,7 @@
#:use-module ((guile) #:select
(@ @@ pk let* lambda call-with-values case-lambda
set! = * + - < <= > >= / pair?
- syntax-rules let-syntax))
+ syntax-rules let-syntax abort-to-prompt))
#:use-module (language python module python)
#:use-module ((language python compile) #:select (pks))
#:use-module (language python exceptions))
@@ -2716,14 +2716,20 @@
#:final l)))))
(define-syntax qset!
- (syntax-rules (cons quote)
- ((_ (cons x y) v)
- (let ((w v))
- (qset! x (car w))
- (qset! y (cdr w))))
- ((_ '() v) (values))
- ((_ x v)
- (set! x v))))
+ (lambda (x)
+ (syntax-case x ()
+ ((_ (cons x y) v)
+ (equal? (syntax->datum #'cons) '(@ (guile) cons))
+ #'(let ((w v))
+ (qset! x (car w))
+ (qset! y (cdr w))))
+
+ ((_ '() v)
+ #'(if (not (null? v))
+ (raise (ValueError "too many values to unpack"))))
+
+ ((_ x v)
+ #'(set! x v)))))
(define-syntax define-
(syntax-rules (cons quote)
diff --git a/modules/language/python/def.scm b/modules/language/python/def.scm
index b2a8de2..1f527e9 100644
--- a/modules/language/python/def.scm
+++ b/modules/language/python/def.scm
@@ -143,10 +143,18 @@
(define-syntax py-apply
(lambda (x)
- (syntax-case x (*)
- ((_ f a ... (* x))
- (and-map (lambda (x) (symbol? (syntax->datum x))) #'(a ...))
- #'(if (pair? x)
+ (syntax-case x ()
+ ((_ f a ... (op x))
+ (and (syntax-case #'op (*)
+ (* #t)
+ (_ #f))
+ (and-map (lambda (q)
+ (syntax-case q (* ** =)
+ ((= _ _) #f)
+ ((* _ ) #f)
+ ((** _ ) #f)
+ (_ #t))) #'(a ...)))
+ #'(if (or (null? x) (pair? x))
(apply f a ... x)
(apply f a ... (to-list x))))
diff --git a/modules/language/python/exceptions.scm b/modules/language/python/exceptions.scm
index 915c9ef..8bc812f 100644
--- a/modules/language/python/exceptions.scm
+++ b/modules/language/python/exceptions.scm
@@ -13,9 +13,11 @@
ZeroDivisionError ArithmeticError
OverflowError RecursionError
Warning DeprecationWarning BytesWarning
+ ResourceWarning
UnicodeDecodeError LookupError IndentationError
KeyboardInterrupt MemoryError NameError
- EOFError UnicodeError))
+ EOFError UnicodeError
+ FileExistsError FileNotFoundError IsADirectoryError ))
(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
@@ -67,7 +69,9 @@
(define StopIteration 'StopIteration)
(define GeneratorExit 'GeneratorExit)
-
+(define-er FileExistsError 'FileExistsError)
+(define-er FileNotFoundError 'FileNotFoundError)
+(define-er IsADirectoryError 'IsADirectoryError)
(define-er UnicodeError 'UnicodeError)
(define-er EOFError 'EOFError)
(define-er MemoryError 'MemoryError)
@@ -119,3 +123,4 @@
(define-wr BytesWarning 'BytesWarning)
(define-wr DepricationWarning 'DeprecationWarning)
+(define-wr ResourceWarning 'ResourceWarning)
diff --git a/modules/language/python/module/_random.scm b/modules/language/python/module/_random.scm
index 74b9492..95ff989 100644
--- a/modules/language/python/module/_random.scm
+++ b/modules/language/python/module/_random.scm
@@ -1,33 +1,404 @@
(define-module (language python module _random)
#:use-module (oop pf-objects)
#:use-module (language python string)
+ #:use-module ((language python module python) #:select (int))
+ #:use-module (language python def)
+ #:use-module (language python try)
+ #:use-module (language python exceptions)
#:export (Random))
(define-syntax-rule (aif it p . l) (let ((it p)) (if p . l)))
+(define PI (* 4 (atan 1)))
+(define TWOPI (* 2 PI))
+(define LOG4 (log 4.0))
+(define _e (exp 1))
+
+(define NV_MAGICCONST (/ (* 4 (exp -0.5)) (sqrt 2.0)))
+(define SG_MAGICCONST (+ 1.0 (log 4.5)))
+
(define-python-class Random ()
(define seed
(lambda (self s)
- (rawset self '_state (seed->random-state (format #f "~a" s)))))
+ (fastset self '_state (seed->random-state (format #f "~a" s)))))
(define setstate
(lambda (self s)
- (rawset self '_state s)))
+ (fastset self '_state s)))
(define getstate
(lambda (self)
- (aif it (rawref self '_state)
+ (aif it (fastref self '_state)
it
(let ((ret (random-state-from-platform)))
- (set self '_state ret)
+ (fastset self '_state ret)
ret))))
+
(define getrandbits '(no))
+
(define random
(lambda (self)
+ (let lp ()
+ (set! *random-state* (getstate self))
+ (let ((x (random:uniform)))
+ (if (= x 1.0)
+ (lp)
+ (begin
+ (fastset self '_state *random-state*)
+ x))))))
+
+
+ (define randrange
+ (lambda* (self start #:optional (stop None) (step 1) (_int int))
+ (define (fallback)
+ ((rawref self '_randrange) self start stop step _int))
+
+ (if (number? start)
+ (if (eq? stop None)
+ (_randbelow self start)
+ (if (number? stop)
+ (begin
+ (if (<= stop start)
+ (raise (ValueError "zero range in randrange")))
+ (if (equal? step 1)
+ (+ start (_randbelow self (- stop start)))
+ (if (number? step)
+ (let* ((width (- stop start))
+ (n (cond
+ ((= step 0)
+ (raise
+ (ValueError
+ "step of 0 is invalĂ­d in randrange")))
+ ((> step 0)
+ (floor-quotient
+ (+ width step - 1) step))
+ (else
+ (floor-quotient
+ (+ width step + 1) step)))))
+ (+ start (* step (_randbelow self n))))
+ (fallback))))
+ (fallback)))
+ (fallback))))
+
+
+ (define randint
+ (lambda (self a b)
+ "Return random integer in range [a, b], including both end points.
+ "
+ (randrange self a b)))
+
+ (define _randbelow
+ (lambda (self n)
+ "Return random integer in range [a, b], including both end points.
+ "
(set! *random-state* (getstate self))
- (let ((x (random:uniform)))
- (rawset self '_state *random-state*)
- x))))
+ (let ((x ((@ (guile) random) n)))
+ (fastset self '_state *random-state*)
+ x)))
+
+
+ ;; -------------------- triangular --------------------
+
+ (define triangular
+ (lambda* (self #:optional (low 0.0) (high 1.0) (mode None))
+ "Triangular distribution.
+
+ Continuous distribution bounded by given lower and upper limits,
+ and having a given mode value in-between.
+
+ http://en.wikipedia.org/wiki/Triangular_distribution
+
+ "
+ (let ((u (random self))
+ (c (if (eq? mode None)
+ 0.5
+ (let ((den (- high low)))
+ (if (= den 0)
+ low
+ (/ (- mode low) 1.0 den))))))
+
+ (if (> u c)
+ (let* ((u (- 1.0 u))
+ (c (- 1.0 c))
+ (t high)
+ (high low)
+ (low high))
+ (+ low (* (- high low) (sqrt (* u c)))))
+ (+ low (* (- high low) (sqrt (* u c))))))))
+
+ ;; -------------------- normal distribution --------------------
+
+ (define normalvariate
+ (lambda (self mu sigma)
+ "Normal distribution.
+
+ mu is the mean, and sigma is the standard deviation.
+
+ "
+ ;; mu = mean, sigma = standard deviation
+
+ ;; Uses Kinderman and Monahan method. Reference: Kinderman,
+ ;; A.J. and Monahan, J.F., "Computer generation of random
+ ;; variables using the ratio of uniform deviates", ACM Trans
+ ;; Math Software, 3, (1977), pp257-260.
+
+ (let lp ()
+ (let* ((u1 (random self))
+ (u2 (- 1.0 (random self)))
+ (z (/ (* NV_MAGICCONST (- u1 0.5)) u2))
+ (zz (/ (* z z) 4.0)))
+ (if (<= zz (- (log u2)))
+ (+ mu (* z sigma))
+ (lp))))))
+
+ ;; -------------------- lognormal distribution --------------------
+
+ (define lognormvariate
+ (lambda (self mu sigma)
+ "Log normal distribution.
+
+ If you take the natural logarithm of this distribution, you'll get a
+ normal distribution with mean mu and standard deviation sigma.
+ mu can have any value, and sigma must be greater than zero.
+
+ "
+ (exp (normalvariate self mu sigma))))
+
+ ;;## -------------------- exponential distribution --------------------
+
+ (define expovariate
+ (lambda (self lambd)
+ "Exponential distribution.
+
+ lambd is 1.0 divided by the desired mean. It should be
+ nonzero. (The parameter would be called \"lambda\", but that is
+ a reserved word in Python.) Returned values range from 0 to
+ positive infinity if lambd is positive, and from negative
+ infinity to 0 if lambd is negative.
+
+ "
+
+ ;; lambd: rate lambd = 1/mean
+ ;; ('lambda' is a Python reserved word)
+
+ ;; we use 1-random() instead of random() to preclude the
+ ;; possibility of taking the log of zero.
+
+ (- (/ (log (- 1.0 (random self))) lambd))))
+
+ ;;## -------------------- gamma distribution --------------------
+
+ (define gammavariate
+ (lambda (self alpha beta)
+ "Gamma distribution. Not the gamma function!
+
+ Conditions on the parameters are alpha > 0 and beta > 0.
+
+ The probability distribution function is:
+
+ x ** (alpha - 1) * math.exp(-x / beta)
+ pdf(x) = --------------------------------------
+ math.gamma(alpha) * beta ** alpha
+
+ "
+
+ ;; alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
+ ;; Warning: a few older sources define the gamma distribution in terms
+ ;; of alpha > -1.0
+
+ (if (or (<= alpha 0.0) (<= beta 0.0))
+ (raise (ValueError "gammavariate: alpha and beta must be > 0.0")))
+
+ (cond
+ ((> alpha 1.0)
+ ;; Uses R.C.H. Cheng, "The generation of Gamma
+ ;; variables with non-integral shape parameters",
+ ;; Applied Statistics, (1977), 26, No. 1, p71-74
+
+ (let* ((ainv (sqrt (- (* 2.0 alpha) 1.0)))
+ (bbb (- alpha LOG4))
+ (ccc (+ alpha ainv)))
+
+ (let lp ()
+ (let ((u1 (random self)))
+ (if (or (< u1 1e-7) (> u1 .9999999))
+ (lp)
+ (let* ((u2 (- 1.0 (random self)))
+ (v (/ (log (/ u1 (- 1.0 u1))) ainv))
+ (x (* alpha (exp v)))
+ (z (* u1 u1 u2))
+ (r (+ bbb (* ccc v) (- x))))
+ (if (or (>= (+ r SG_MAGICCONST (- (* 4.5 z))) 0.0)
+ (>= r (log z)))
+ (* x beta)
+ (lp))))))))
+
+ ((= alpha 1.0)
+ ;; expovariate(1)
+ (let lp ((u (random self)))
+ (if (<= u 1e-7)
+ (lp (random self))
+ (- (* (log u) beta)))))
+
+ (else
+ ;;alpha is between 0 and 1 (exclusive)
+ ;; Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
+
+ (let lp ()
+ (let* ((u (random self))
+ (b (/ (+ _e alpha) _e))
+ (p (* b u))
+ (x (if (<= p 1.0)
+ (expt p (/ 1.0 alpha))
+ (- (log (/ (- b p) alpha)))))
+ (u1 (random self)))
+ (if (> p 1.0)
+ (if (<= u1 (expt x (- alpha 1.0)))
+ (* x beta)
+ (lp))
+ (if (<= u1 (exp (- x)))
+ (* x beta)
+ (lp)))))))))
+
+ ;; -------------------- beta --------------------
+ ;; See
+ ;; http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
+ ;; for Ivan Frohne's insightful analysis of why the original implementation:
+ ;;
+ ;; def betavariate(self, alpha, beta):
+ ;; # Discrete Event Simulation in C, pp 87-88.
+ ;;
+ ;; y = self.expovariate(alpha)
+ ;; z = self.expovariate(1.0/beta)
+ ;; return z/(y+z)
+ ;;
+ ;; was dead wrong, and how it probably got that way.
+
+ (define betavariate
+ (lambda (self alpha beta)
+ "Beta distribution.
+
+ Conditions on the parameters are alpha > 0 and beta > 0.
+ Returned values range between 0 and 1.
+
+ "
+
+ ;; This version due to Janne Sinkkonen, and matches all the std
+ ;; texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
+ (let ((y (gammavariate self alpha 1.0)))
+ (if (= y 0)
+ 0.0
+ (/ y (+ y (gammavariate self beta 1.0)))))))
+
+ ;; -------------------- von Mises distribution --------------------
+
+ (define vonmisesvariate
+ (lambda (self mu kappa)
+ "Circular data distribution.
+
+ mu is the mean angle, expressed in radians between 0 and 2*pi, and
+ kappa is the concentration parameter, which must be greater than or
+ equal to zero. If kappa is equal to zero, this distribution reduces
+ to a uniform random angle over the range 0 to 2*pi.
+
+ "
+ ;; mu: mean angle (in radians between 0 and 2*pi)
+ ;; kappa: concentration parameter kappa (>= 0)
+ ;; if kappa = 0 generate uniform random angle
+
+ ;; Based upon an algorithm published in: Fisher, N.I.,
+ ;; "Statistical Analysis of Circular Data", Cambridge
+ ;; University Press, 1993.
+
+ ;; Thanks to Magnus Kessler for a correction to the
+ ;; implementation of step 4.
+
+ (if (<= kappa 1e-6)
+ (* TWOPI (random self))
+ (let* ((s (/ 0.5 kappa))
+ (r (+ s (sqrt (+ 1.0 (* s s))))))
+ (let lp ()
+ (let* ((u1 (random self))
+ (z (cos (* PI u1)))
+ (d (/ z (+ r z)))
+ (u2 (random self)))
+ (if (or (< u2 (- 1.0 (* d d)))
+ (<= u2 (* (- 1.0 d) (exp d))))
+ (let* ((q (/ 1.0 r))
+ (f (/ (+ q z) (+ 1.0 (* q z))))
+ (u3 (random self)))
+ (if (> u3 0.5)
+ (floor-remainder (+ mu (acos f)) TWOPI)
+ (floor-remainder (- mu (acos f)) TWOPI)))
+ (lp))))))))
+
+ (define uniform
+ (lambda (self a b)
+ "Get a random number in the range [a, b) or [a, b] depending on rounding."
+ (+ a (* (- b a) (random self)))))
+
+
+ ;; -------------------- Pareto --------------------
+ (define paretovariate
+ (lambda (self alpha)
+ "Pareto distribution. alpha is the shape parameter."
+ ;; Jain, pg. 495
+
+ (let ((u (- 1.0 (random self))))
+ (/ 1.0 (expt u (/ 1.0 alpha))))))
+
+ ;; -------------------- Weibull --------------------
+ (define weibullvariate
+ (lambda (self alpha beta)
+ "Weibull distribution.
+
+ alpha is the scale parameter and beta is the shape parameter.
+
+ "
+ ;; Jain, pg. 499; bug fix courtesy Bill Arms
+
+ (let ((u (- 1.0 (random self))))
+ (* alpha (expt (- (log u)) (/ 1.0 beta))))))
+
+
+ (define gauss
+ (lambda (self mu sigma)
+ "Gaussian distribution.
+
+ mu is the mean, and sigma is the standard deviation. This is
+ slightly faster than the normalvariate() function.
+
+ Not thread-safe without a lock around calls.
+
+ "
+
+ ;; When x and y are two variables from [0, 1), uniformly
+ ;; distributed, then
+ ;;
+ ;; cos(2*pi*x)*sqrt(-2*log(1-y))
+ ;; sin(2*pi*x)*sqrt(-2*log(1-y))
+ ;;
+ ;; are two *independent* variables with normal distribution
+ ;; (mu = 0, sigma = 1).
+ ;; (Lambert Meertens)
+ ;; (corrected version; bug discovered by Mike Miller, fixed by LM)
+
+ ;; Multithreading note: When two threads call this function
+ ;; simultaneously, it is possible that they will receive the
+ ;; same return value. The window is very small though. To
+ ;; avoid this, you have to use a lock around all calls. (I
+ ;; didn't want to slow this down in the serial case by using a
+ ;; lock here.)
+
+ (let ((z (fastref self 'gauss_next)))
+ (fastset self 'gauss_next #f)
+ (if (not z)
+ (let ((x2pi (* (random self) TWOPI))
+ (g2rad (sqrt (* -2.0 (log (- 1.0 (random self)))))))
+ (set! z (* (cos x2pi) g2rad))
+ (fastset self 'gauss_next (* (sin x2pi) g2rad))))
+
+ (+ mu (* z sigma))))))
diff --git a/modules/language/python/module/io.scm b/modules/language/python/module/io.scm
index 058e62d..3c7809c 100644
--- a/modules/language/python/module/io.scm
+++ b/modules/language/python/module/io.scm
@@ -158,9 +158,11 @@
newline closefd opener)
path)
mode)))
- (if (member #\b (string->list mode))
- F
- (TextIOWrapper F encoding errors))))
+ (let ((r (if (member #\b (string->list mode))
+ F
+ (TextIOWrapper F encoding errors))))
+ (set r '_closefd closefd)
+ r)))
(define-syntax check
diff --git a/modules/language/python/module/os.scm b/modules/language/python/module/os.scm
index e4dc72c..764c701 100644
--- a/modules/language/python/module/os.scm
+++ b/modules/language/python/module/os.scm
@@ -114,6 +114,8 @@
RTLD_NOLOAD RTLD_DEEPBIND
getrandom urandom GRND_NONBLOCK GRND_RANDOM
+
+ sys
))
(define supports_dir_fd
@@ -135,7 +137,14 @@
(define-syntax-rule (ca code)
(catch #t
(lambda () code)
- (lambda x (raise error x))))
+ (lambda x
+ (match x
+ (('system-error x _ _ (17))
+ (raise (FileExistsError x)))
+ (('system-error x _ _ (2))
+ (raise (FileNotFoundError x)))
+ (x (raise error x))))))
+
(define-syntax-rule (rm code)
(let ((r (ca code)))
(if (< r 0)
@@ -442,7 +451,7 @@
(define close
(lambda (fd)
- (ca ((@ (guile) close-fdes) fd))))
+ (ca ((@ (guile) close) fd))))
(define (closerange fd_low fd_high)
(for ((i : (range fd_low fd_high))) ()
@@ -2363,3 +2372,5 @@
p)
(py-list l)))
+(define-python-class sys ()
+ (define platform "posix"))
diff --git a/modules/language/python/module/random.py b/modules/language/python/module/random.py
index 4c24977..be8f9ef 100644
--- a/modules/language/python/module/random.py
+++ b/modules/language/python/module/random.py
@@ -92,8 +92,8 @@ class Random (_random.Random):
"""
self.seed(x)
- self.gauss_next = None
-
+ self.gauss_next = False
+
def seed(self, a=None, version=2):
"""Initialize internal state from hashable object.
@@ -124,7 +124,7 @@ class Random (_random.Random):
a = int.from_bytes(a, 'big')
super().seed(a)
- self.gauss_next = None
+ self.gauss_next = False
def getstate(self):
"""Return internal state; can be passed to setstate() later."""
@@ -169,9 +169,9 @@ class Random (_random.Random):
def __reduce__(self):
return self.__class__, (), self.getstate()
-## -------------------- integer methods -------------------
+ ## -------------------- integer methods -------------------
- def randrange(self, start, stop=None, step=1, _int=int):
+ def _randrange_(self, start, stop, step, _int):
"""Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
@@ -182,7 +182,6 @@ class Random (_random.Random):
# This code is a bit messy to make it fast for the
# common case while still doing adequate error checking.
istart = _int(start)
-
if istart != start:
raise ValueError("non-integer arg 1 for randrange()")
if stop is None:
@@ -192,11 +191,9 @@ class Random (_random.Random):
# stop argument supplied.
istop = _int(stop)
-
if istop != stop:
raise ValueError("non-integer stop for randrange()")
width = istop - istart
-
if step == 1 and width > 0:
return istart + self._randbelow(width)
if step == 1:
@@ -218,45 +215,6 @@ class Random (_random.Random):
return istart + istep*self._randbelow(n)
- def randint(self, a, b):
- """Return random integer in range [a, b], including both end points.
- """
-
- return self.randrange(a, b+1)
-
- def _randbelow(self, n, int=int, maxsize=1<<BPF, type=type,
- Method=_MethodType, BuiltinMethod=_BuiltinMethodType):
- "Return a random int in the range [0,n). Raises ValueError if n==0."
-
- random = self.random
- getrandbits = self.getrandbits
-
- # Only call self.getrandbits if the original random() builtin method
- # has not been overridden or if a new getrandbits() was supplied.
- if type(random) is BuiltinMethod or type(getrandbits) is Method:
- k = n.bit_length() # don't use (n-1) here because n can be 1
- r = getrandbits(k) # 0 <= r < 2**k
- while r >= n:
- r = getrandbits(k)
- return r
-
- # There's an overridden random() method but no new getrandbits() method,
- # so we can only use random() from here.
- if n >= maxsize:
- _warn("Underlying random() generator does not supply \n"
- "enough bits to choose from a population range this large.\n"
- "To remove the range limitation, add a getrandbits() method.")
- return int(random() * n)
-
- rem = maxsize % n
- limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0
-
- r = random()
- while r >= limit:
- r = random()
-
- return int(r*maxsize) % n
-
## -------------------- sequence methods -------------------
def choice(self, seq):
@@ -373,300 +331,7 @@ class Random (_random.Random):
## -------------------- uniform distribution -------------------
- def uniform(self, a, b):
- "Get a random number in the range [a, b) or [a, b] depending on rounding."
- return a + (b-a) * self.random()
-
-## -------------------- triangular --------------------
-
- def triangular(self, low=0.0, high=1.0, mode=None):
- """Triangular distribution.
-
- Continuous distribution bounded by given lower and upper limits,
- and having a given mode value in-between.
-
- http://en.wikipedia.org/wiki/Triangular_distribution
-
- """
- u = self.random()
- try:
- c = 0.5 if mode is None else (mode - low) / (high - low)
- except ZeroDivisionError:
- return low
- if u > c:
- u = 1.0 - u
- c = 1.0 - c
- low, high = high, low
- return low + (high - low) * (u * c) ** 0.5
-
-## -------------------- normal distribution --------------------
-
- def normalvariate(self, mu, sigma):
- """Normal distribution.
-
- mu is the mean, and sigma is the standard deviation.
-
- """
- # mu = mean, sigma = standard deviation
-
- # Uses Kinderman and Monahan method. Reference: Kinderman,
- # A.J. and Monahan, J.F., "Computer generation of random
- # variables using the ratio of uniform deviates", ACM Trans
- # Math Software, 3, (1977), pp257-260.
-
- random = self.random
- while 1:
- u1 = random()
- u2 = 1.0 - random()
- z = NV_MAGICCONST*(u1-0.5)/u2
- zz = z*z/4.0
- if zz <= -_log(u2):
- break
- return mu + z*sigma
-
-## -------------------- lognormal distribution --------------------
-
- def lognormvariate(self, mu, sigma):
- """Log normal distribution.
-
- If you take the natural logarithm of this distribution, you'll get a
- normal distribution with mean mu and standard deviation sigma.
- mu can have any value, and sigma must be greater than zero.
-
- """
- return _exp(self.normalvariate(mu, sigma))
-
-## -------------------- exponential distribution --------------------
-
- def expovariate(self, lambd):
- """Exponential distribution.
-
- lambd is 1.0 divided by the desired mean. It should be
- nonzero. (The parameter would be called "lambda", but that is
- a reserved word in Python.) Returned values range from 0 to
- positive infinity if lambd is positive, and from negative
- infinity to 0 if lambd is negative.
-
- """
- # lambd: rate lambd = 1/mean
- # ('lambda' is a Python reserved word)
-
- # we use 1-random() instead of random() to preclude the
- # possibility of taking the log of zero.
- return -_log(1.0 - self.random())/lambd
-
-## -------------------- von Mises distribution --------------------
-
- def vonmisesvariate(self, mu, kappa):
- """Circular data distribution.
-
- mu is the mean angle, expressed in radians between 0 and 2*pi, and
- kappa is the concentration parameter, which must be greater than or
- equal to zero. If kappa is equal to zero, this distribution reduces
- to a uniform random angle over the range 0 to 2*pi.
-
- """
- # mu: mean angle (in radians between 0 and 2*pi)
- # kappa: concentration parameter kappa (>= 0)
- # if kappa = 0 generate uniform random angle
-
- # Based upon an algorithm published in: Fisher, N.I.,
- # "Statistical Analysis of Circular Data", Cambridge
- # University Press, 1993.
-
- # Thanks to Magnus Kessler for a correction to the
- # implementation of step 4.
-
- random = self.random
- if kappa <= 1e-6:
- return TWOPI * random()
-
- s = 0.5 / kappa
- r = s + _sqrt(1.0 + s * s)
-
- while 1:
- u1 = random()
- z = _cos(_pi * u1)
-
- d = z / (r + z)
- u2 = random()
- if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
- break
-
- q = 1.0 / r
- f = (q + z) / (1.0 + q * z)
- u3 = random()
- if u3 > 0.5:
- theta = (mu + _acos(f)) % TWOPI
- else:
- theta = (mu - _acos(f)) % TWOPI
-
- return theta
-
-## -------------------- gamma distribution --------------------
-
- def gammavariate(self, alpha, beta):
- """Gamma distribution. Not the gamma function!
-
- Conditions on the parameters are alpha > 0 and beta > 0.
-
- The probability distribution function is:
-
- x ** (alpha - 1) * math.exp(-x / beta)
- pdf(x) = --------------------------------------
- math.gamma(alpha) * beta ** alpha
-
- """
-
- # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
-
- # Warning: a few older sources define the gamma distribution in terms
- # of alpha > -1.0
- if alpha <= 0.0 or beta <= 0.0:
- raise ValueError('gammavariate: alpha and beta must be > 0.0')
-
- random = self.random
- if alpha > 1.0:
-
- # Uses R.C.H. Cheng, "The generation of Gamma
- # variables with non-integral shape parameters",
- # Applied Statistics, (1977), 26, No. 1, p71-74
-
- ainv = _sqrt(2.0 * alpha - 1.0)
- bbb = alpha - LOG4
- ccc = alpha + ainv
-
- while 1:
- u1 = random()
- if not 1e-7 < u1 < .9999999:
- continue
- u2 = 1.0 - random()
- v = _log(u1/(1.0-u1))/ainv
- x = alpha*_exp(v)
- z = u1*u1*u2
- r = bbb+ccc*v-x
- if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
- return x * beta
-
- elif alpha == 1.0:
- # expovariate(1)
- u = random()
- while u <= 1e-7:
- u = random()
- return -_log(u) * beta
-
- else: # alpha is between 0 and 1 (exclusive)
-
- # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
-
- while 1:
- u = random()
- b = (_e + alpha)/_e
- p = b*u
- if p <= 1.0:
- x = p ** (1.0/alpha)
- else:
- x = -_log((b-p)/alpha)
- u1 = random()
- if p > 1.0:
- if u1 <= x ** (alpha - 1.0):
- break
- elif u1 <= _exp(-x):
- break
- return x * beta
-
-## -------------------- Gauss (faster alternative) --------------------
-
- def gauss(self, mu, sigma):
- """Gaussian distribution.
-
- mu is the mean, and sigma is the standard deviation. This is
- slightly faster than the normalvariate() function.
-
- Not thread-safe without a lock around calls.
-
- """
-
- # When x and y are two variables from [0, 1), uniformly
- # distributed, then
- #
- # cos(2*pi*x)*sqrt(-2*log(1-y))
- # sin(2*pi*x)*sqrt(-2*log(1-y))
- #
- # are two *independent* variables with normal distribution
- # (mu = 0, sigma = 1).
- # (Lambert Meertens)
- # (corrected version; bug discovered by Mike Miller, fixed by LM)
-
- # Multithreading note: When two threads call this function
- # simultaneously, it is possible that they will receive the
- # same return value. The window is very small though. To
- # avoid this, you have to use a lock around all calls. (I
- # didn't want to slow this down in the serial case by using a
- # lock here.)
-
- random = self.random
- z = self.gauss_next
- self.gauss_next = None
- if z is None:
- x2pi = random() * TWOPI
- g2rad = _sqrt(-2.0 * _log(1.0 - random()))
- z = _cos(x2pi) * g2rad
- self.gauss_next = _sin(x2pi) * g2rad
-
- return mu + z*sigma
-
-## -------------------- beta --------------------
-## See
-## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
-## for Ivan Frohne's insightful analysis of why the original implementation:
-##
-## def betavariate(self, alpha, beta):
-## # Discrete Event Simulation in C, pp 87-88.
-##
-## y = self.expovariate(alpha)
-## z = self.expovariate(1.0/beta)
-## return z/(y+z)
-##
-## was dead wrong, and how it probably got that way.
-
- def betavariate(self, alpha, beta):
- """Beta distribution.
-
- Conditions on the parameters are alpha > 0 and beta > 0.
- Returned values range between 0 and 1.
-
- """
-
- # This version due to Janne Sinkkonen, and matches all the std
- # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
- y = self.gammavariate(alpha, 1.0)
- if y == 0:
- return 0.0
- else:
- return y / (y + self.gammavariate(beta, 1.0))
-
-## -------------------- Pareto --------------------
-
- def paretovariate(self, alpha):
- """Pareto distribution. alpha is the shape parameter."""
- # Jain, pg. 495
-
- u = 1.0 - self.random()
- return 1.0 / u ** (1.0/alpha)
-
-## -------------------- Weibull --------------------
-
- def weibullvariate(self, alpha, beta):
- """Weibull distribution.
-
- alpha is the scale parameter and beta is the shape parameter.
-
- """
- # Jain, pg. 499; bug fix courtesy Bill Arms
- u = 1.0 - self.random()
- return alpha * (-_log(u)) ** (1.0/beta)
## --------------- Operating System Random Source ------------------
@@ -750,10 +415,14 @@ def _test_generator0(n, func):
print('avg %g, stddev %g, min %g, max %g\n' % \
(avg, stddev, smallest, largest))
+x = _random.Random()
+rand = x.random
def _test(N=2000):
+ _test_generator(N, randint, (10, 20))
_test_generator(N, random, ())
_test_generator0(N, random)
+ _test_generator0(N, rand)
_test_generator(N, normalvariate, (0.0, 1.0))
_test_generator(N, lognormvariate, (0.0, 1.0))
_test_generator(N, vonmisesvariate, (0.0, 1.0))
diff --git a/modules/language/python/module/threading.scm b/modules/language/python/module/threading.scm
index c2dd77c..73d6cba 100644
--- a/modules/language/python/module/threading.scm
+++ b/modules/language/python/module/threading.scm
@@ -32,4 +32,5 @@
(define release __leave__))
-
+(define allocate_lock
+ (lambda () (RLock)))
diff --git a/modules/language/python/string.scm b/modules/language/python/string.scm
index a189d84..ad80a87 100644
--- a/modules/language/python/string.scm
+++ b/modules/language/python/string.scm
@@ -601,18 +601,20 @@
(define-python-class string (<py-string>)
(define __init__
(case-lambda
- ((self s . l)
- (cond
- ((is-a? s <py-string>)
- (slot-ref s 'str))
- ((is-a? s <string>)
- s)
- ((b? s)
- (apply b-decode s l))
- (else
- (aif it (ref s '__str__)
- (it)
- (__init__ self ((@ (guile) format) #f "~a" s))))))))
+ ((self)
+ "")
+ ((self s . l)
+ (cond
+ ((is-a? s <py-string>)
+ (slot-ref s 'str))
+ ((is-a? s <string>)
+ s)
+ ((b? s)
+ (apply b-decode s l))
+ (else
+ (aif it (ref s '__str__)
+ (it)
+ (__init__ self ((@ (guile) format) #f "~a" s))))))))
(define __new__
diff --git a/modules/oop/pf-objects.scm b/modules/oop/pf-objects.scm
index 0e2f1d9..47dea90 100644
--- a/modules/oop/pf-objects.scm
+++ b/modules/oop/pf-objects.scm
@@ -18,7 +18,7 @@
*class* *self* pyobject? pytype?
type object pylist-set! pylist-ref tr
resolve-method-g rawref rawset py-dict
- ref-class
+ ref-class fastref fastset
))
#|
@@ -35,6 +35,7 @@ The datastructure is functional but the objects mutate. So one need to
explicitly tell it to not update etc.
|#
+
(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
;; this is mutated by the dict class
@@ -144,6 +145,20 @@ explicitly tell it to not update etc.
(name-object <pyf>)
(name-object <property>)
+(define (fastref o k . e)
+ (define r (if (pair? e) (car e) #f))
+ (let ((h (slot-ref o 'h)))
+ (if (hash-table? h)
+ (hash-ref (slot-ref o 'h) k r)
+ (aif it (vhash-assoc k (slot-ref o 'h)) (cdr it) r))))
+
+(define (fastset o k v)
+ (let ((h (slot-ref o 'h)))
+ (if (hash-table? h)
+ (hash-set! (slot-ref o 'h) k v)
+ (slot-set! o 'h
+ (vhash-cons k v (slot-ref o 'h))))))
+
(define-method (pylist-set! (o <p>) key val)
(aif it (ref o '__setitem__)
(it key val)
@@ -247,7 +262,7 @@ explicitly tell it to not update etc.
(if (pytype? cls)
(lambda x (apply f obj x))
f)
- (if (pyclass? cls)
+ (if (pyclass? cls)
(lambda x (apply f obj x))
f)))))
@@ -730,7 +745,7 @@ explicitly tell it to not update etc.
#f)))
(define-syntax-rule (mox o x)
- (if (procedure? x)
+ (if (and (procedure? x) (not (is-a? x <p>)))
(aif it (procedure-property- x '__get__)
(it x o (fluid-ref *location*))
x)))