# HG changeset patch # User Steve Losh # Date 1471542453 0 # Node ID 25f352f9235605b2a27ee0a86600a56d71f1cf72 # Parent f556a4cf23b08004c1e9d4141e822cbeca403bfb Add `within-radius` iterate driver diff -r f556a4cf23b0 -r 25f352f92356 Makefile --- a/Makefile Thu Aug 18 16:16:00 2016 +0000 +++ b/Makefile Thu Aug 18 17:47:33 2016 +0000 @@ -1,4 +1,4 @@ -.PHONY: +.PHONY: docs sourcefiles = $(shell ffind --full-path --literal .lisp) @@ -8,3 +8,5 @@ DOCUMENTATION.markdown: $(sourcefiles) sbcl --noinform --load make-docs.lisp --eval '(quit)' +docs: DOCUMENTATION.markdown + diff -r f556a4cf23b0 -r 25f352f92356 losh.lisp --- a/losh.lisp Thu Aug 18 16:16:00 2016 +0000 +++ b/losh.lisp Thu Aug 18 17:47:33 2016 +0000 @@ -833,6 +833,39 @@ ,on-cycle) ,%counter)))))))) + +(defmacro-clause (GENERATE-NESTED forms CONTROL-VAR control-var) + (iterate + (for (var . args) :in forms) + (for prev :previous var :initially nil) + + ;; we basically turn + ;; (for-nested ((x :from 0 :to n) + ;; (y :from 0 :to m) + ;; (z :from 0 :to q))) + ;; into + ;; (generate x :from 0 :to n) + ;; (generate y :cycling (next x) :from 0 :to m) + ;; (generate z :cycling (next y) :from 0 :to q) + ;; (generate control-var + ;; :next (if-first-time + ;; (progn (next x) (next y) (next z)) + ;; (next z))) + (collect var :into vars) + (collect `(generate ,var + ,@(when prev `(:cycling (next ,prev))) + ,@args) + :into cycling-forms) + + (finally (return `(progn + ,@cycling-forms + (declare (ignorable ,control-var)) + (generate ,control-var :next + (if-first-time + (progn ,@(iterate (for v :in vars) + (collect `(next ,v)))) + (next ,var)))))))) + (defmacro-clause (FOR-NESTED forms) "Iterate the given `forms` in a nested fashion. @@ -863,33 +896,72 @@ (3 0.8) " - (iterate - (for (var . args) :in forms) - (for prev :previous var :initially nil) + (with-gensyms (control) + `(progn + (generate-nested ,forms :control-var ,control) + (next ,control)))) + + +(defmacro-clause (FOR delta-vars WITHIN-RADIUS radius &optional + SKIP-ORIGIN should-skip-origin) + "Iterate through a number of delta values within a given radius. + + Imagine you have a 2D array and you want to find all the neighbors of a given + cell: + + ......... + ...nnn... + ...nXn... + ...nnn... + ......... + + You'll need to iterate over the cross product of the array indices from + `(- target 1)` to `(+ target 1)`. + + You may want to have a larger radius, and you may or may not want to include + the origin (delta `(0 0)`). + + This clause handles calculating the deltas for you, without needless consing. + + Examples: - ;; we basically turn - ;; (for-nested ((x :from 0 :to n) - ;; (y :from 0 :to m) - ;; (z :from 0 :to q))) - ;; into - ;; (generate x :from 0 :to n) - ;; (generate y :cycling (next x) :from 0 :to m) - ;; (generate z :cycling (next y) :from 0 :to q) - ;; (if-first-time - ;; (progn (next x) (next y) (next z)) - ;; (next z)) - (collect var :into vars) - (collect `(generate ,var - ,@(when prev `(:cycling (next ,prev))) - ,@args) - :into cycling-forms) + (iterate (for (x) :within-radius 2) + (collect (list x))) + => + ((-2) (-1) (0) (1) (2)) + + (iterate (for (x y) :within-radius 1 :skip-origin t) + (collect (list x y))) + => + ((-1 -1) + (-1 0) + (-1 1) + ( 0 -1) + ( 0 1) + ( 1 -1) + ( 1 0) + ( 1 1)) - (finally (return `(progn - ,@cycling-forms - (if-first-time - (progn ,@(iterate (for v :in vars) - (collect `(next ,v)))) - (next ,var))))))) + (iterate (for (x y z) :within-radius 3) + (collect (list x y z))) + => + ; ... a bigass list of deltas, + ; the point it is works in arbitrary dimensions. + + " + (with-gensyms (r -r control skip) + `(progn + (with ,r = ,radius) + (with ,-r = (- ,r)) + (with ,skip = ,should-skip-origin) + (generate-nested ,(iterate (for var :in delta-vars) + (collect `(,var :from ,-r :to ,r))) + :control-var ,control) + (next ,control) + (when (and ,skip + ,@(iterate (for var :in delta-vars) + (collect `(zerop ,var)))) + (next ,control))))) ;;;; Distributions diff -r f556a4cf23b0 -r 25f352f92356 package.lisp --- a/package.lisp Thu Aug 18 16:16:00 2016 +0000 +++ b/package.lisp Thu Aug 18 17:47:33 2016 +0000 @@ -132,7 +132,9 @@ #:across-flat-array #:index-of-flat-array #:cycling - #:for-nested)) + #:for-nested + #:within-radius + #:skip-origin)) (defsubpackage #:losh.distributions (:documentation "Utilities for calculating statistical... things.")