(ql:quickload '(:alexandria :png :iterate :flexi-streams :lparallel :cl-cpus))
To load "alexandria": Load 1 ASDF system: alexandria ; Loading "alexandria" To load "png": Load 3 ASDF systems: asdf cffi cffi-grovel Install 1 Quicklisp release: cl-png ; Fetching #<URL "http://beta.quicklisp.org/archive/cl-png/2020-09-25/cl-png-vl-anyversion-11b965fe-git.tgz"> ; 8311.11KB ================================================== 8,510,578 bytes in 0.56 seconds (14929.84KB/sec) ; Loading "png" [package image]................................... [package png]; cc -o /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel-tmpXGI96G7.o -c -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -D_GNU_SOURCE -fno-omit-frame-pointer -DSBCL_HOME=/usr/lib/sbcl -g -Wall -Wundef -Wsign-compare -Wpointer-arith -O3 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wunused-parameter -fno-omit-frame-pointer -momit-leaf-frame-pointer -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/X11/include -I/opt/local/include -fPIC -I/home/yitzi/quicklisp/dists/quicklisp/software/cffi_0.24.1/ /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel.c ; cc -o /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel-tmpF0KDNX6B -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -g -Wl,--export-dynamic /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel.o ; /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/grovel__grovel.grovel-tmp.lisp .; cc -o /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/wrappers__wrapper-tmpWKYU2CYG.o -c -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -D_GNU_SOURCE -fno-omit-frame-pointer -DSBCL_HOME=/usr/lib/sbcl -g -Wall -Wundef -Wsign-compare -Wpointer-arith -O3 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wunused-parameter -fno-omit-frame-pointer -momit-leaf-frame-pointer -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/X11/include -I/opt/local/include -fPIC -I/home/yitzi/quicklisp/dists/quicklisp/software/cffi_0.24.1/ /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/wrappers__wrapper.c ; cc -o /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/wrappers.so -shared -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -D_GNU_SOURCE -fno-omit-frame-pointer -DSBCL_HOME=/usr/lib/sbcl -g -Wall -Wundef -Wsign-compare -Wpointer-arith -O3 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wunused-parameter -fno-omit-frame-pointer -momit-leaf-frame-pointer /home/yitzi/.cache/common-lisp/sbcl-2.1.1-linux-x64/home/yitzi/quicklisp/dists/quicklisp/software/cl-png-vl-anyversion-11b965fe-git/wrappers__wrapper.o .................................... [package bmp]..................................... [package pnm]...... To load "iterate": Load 1 ASDF system: asdf Install 1 Quicklisp release: iterate ; Fetching #<URL "http://beta.quicklisp.org/archive/iterate/2021-02-28/iterate-20210228-git.tgz"> ; 325.03KB ================================================== 332,831 bytes in 0.07 seconds (4432.13KB/sec) ; Loading "iterate" [package iterate].......................... To load "flexi-streams": Load 2 ASDF systems: asdf trivial-gray-streams Install 1 Quicklisp release: flexi-streams ; Fetching #<URL "http://beta.quicklisp.org/archive/flexi-streams/2020-09-25/flexi-streams-20200925-git.tgz"> ; 431.82KB ================================================== 442,184 bytes in 0.09 seconds (4982.41KB/sec) ; Loading "flexi-streams" [package flexi-streams]........................... .................................................. .................................................. ................................ To load "lparallel": Load 1 ASDF system: lparallel ; Loading "lparallel" [package lparallel.util].......................... [package lparallel.thread-util]................... [package lparallel.raw-queue]..................... [package lparallel.cons-queue].................... [package lparallel.vector-queue].................. [package lparallel.queue]......................... [package lparallel.counter]....................... [package lparallel.spin-queue].................... [package lparallel.kernel]........................ [package lparallel.kernel-util]................... [package lparallel.promise]....................... [package lparallel.ptree]......................... [package lparallel.slet].......................... [package lparallel.defpun]........................ [package lparallel.cognate]....................... [package lparallel] To load "cl-cpus": Load 2 ASDF systems: asdf cffi Install 1 Quicklisp release: cl-cpus ; Fetching #<URL "http://beta.quicklisp.org/archive/cl-cpus/2018-04-30/cl-cpus-20180430-git.tgz"> ; 2.45KB ================================================== 2,505 bytes in 0.00 seconds (0.00KB/sec) ; Loading "cl-cpus" [package cl-cpus]
(:ALEXANDRIA :PNG :ITERATE :FLEXI-STREAMS :LPARALLEL :CL-CPUS)
(setf lparallel:*kernel* (lparallel:make-kernel (cpus:get-number-of-processors)))
#<LPARALLEL.KERNEL:KERNEL :NAME "lparallel" :WORKER-COUNT 4 :USE-CALLER NIL :ALIVE T :SPIN-COUNT 2000 {100420FDE3}>
(defun julia-count (z c &key (max 255))
(do ((i 0 (1+ i))
(p z (+ (expt p 2) c)))
((or (= i max)
(> (abs p) 2))
i)))
JULIA-COUNT
(defclass julia-widget (jupyter-widgets:grid-box)
((image
:reader julia-image
:initform (make-instance 'jupyter-widgets:image
:width 640 :height 640
:layout (make-instance 'jupyter-widgets:layout :grid-area "image")))
(frame
:reader julia-frame
:initform (png:make-image 640 640 1 8))
(x
:reader julia-x
:initform (make-instance 'jupyter-widgets:float-text
:value 0 :description "x"
:layout (make-instance 'jupyter-widgets:layout :grid-area "x")))
(y
:reader julia-y
:initform (make-instance 'jupyter-widgets:float-text
:value 0 :description "y"
:layout (make-instance 'jupyter-widgets:layout :grid-area "y")))
(size
:reader julia-size
:initform (make-instance 'jupyter-widgets:float-text
:value 4 :description "size"
:layout (make-instance 'jupyter-widgets:layout :grid-area "size")))
(ca
:reader julia-ca
:initform (make-instance 'jupyter-widgets:float-text
:value -0.8 :step 0.001 :description "ca"
:layout (make-instance 'jupyter-widgets:layout :grid-area "ca")))
(cb
:reader julia-cb
:initform (make-instance 'jupyter-widgets:float-text
:value 0.156 :step 0.001 :description "cb"
:layout (make-instance 'jupyter-widgets:layout :grid-area "cb")))
(progress
:reader julia-progress
:initform (make-instance 'jupyter-widgets:int-progress
:description "Progress"
:max 640
:layout (make-instance 'jupyter-widgets:layout :grid-area "progress")))
(task-channel
:reader julia-task-channel
:initform (lparallel:make-channel)))
(:metaclass jupyter-widgets:trait-metaclass)
(:default-initargs
:layout (make-instance 'jupyter-widgets:layout
:grid-gap ".25em"
:grid-template-columns "1fr min-content"
:grid-template-rows "min-content min-content min-content min-content min-content min-content 1fr"
:grid-template-areas "\"image x\" \"image y\" \"image size\" \"image ca\" \"image cb\" \"image progress\" \"image .\"")))
(defun calculate-row (frame y c width height xmin xmax ymin ymax)
(let ((zy (+ ymin (* (coerce (/ y height) 'float) (- ymax ymin)))))
(dotimes (x width)
(setf (aref frame y x 0)
(- 255 (julia-count (complex (+ xmin (* (coerce (/ x width) 'float) (- xmax xmin))) zy) c))))))
(defun update (instance)
(bordeaux-threads:make-thread
(lambda ()
(with-slots (task-channel image frame x y size ca cb progress) instance
(let* ((c (complex (jupyter-widgets:widget-value ca)
(jupyter-widgets:widget-value cb)))
(x-value (jupyter-widgets:widget-value x))
(y-value (jupyter-widgets:widget-value y))
(size-value (jupyter-widgets:widget-value size))
(width (jupyter-widgets:widget-width image))
(height (jupyter-widgets:widget-height image))
(xmin (- x-value (/ size-value 2)))
(xmax (+ x-value (/ size-value 2)))
(ymin (- y-value (/ size-value 2)))
(ymax (+ y-value (/ size-value 2))))
(dotimes (y height)
(lparallel:submit-task task-channel #'calculate-row frame y c width height xmin xmax ymin ymax))
(dotimes (y height)
(lparallel:receive-result task-channel)
(setf (jupyter-widgets:widget-value progress) y))
(setf (jupyter-widgets:widget-value image)
(flexi-streams:with-output-to-sequence (o)
(png:encode frame o))))))))
(defmethod initialize-instance :after ((instance julia-widget) &rest initargs &key &allow-other-keys)
(declare (ignore initargs))
(jupyter-widgets:observe (julia-x instance) :value
(lambda (inst type name old-value new-value source)
(declare (ignore inst type name old-value new-value source))
(update instance)))
(jupyter-widgets:observe (julia-y instance) :value
(lambda (inst type name old-value new-value source)
(declare (ignore inst type name old-value new-value source))
(update instance)))
(jupyter-widgets:observe (julia-size instance) :value
(lambda (inst type name old-value new-value source)
(declare (ignore inst type name old-value new-value source))
(update instance)))
(jupyter-widgets:observe (julia-ca instance) :value
(lambda (inst type name old-value new-value source)
(declare (ignore inst type name old-value new-value source))
(update instance)))
(jupyter-widgets:observe (julia-cb instance) :value
(lambda (inst type name old-value new-value source)
(declare (ignore inst type name old-value new-value source))
(update instance)))
(setf (jupyter-widgets:widget-children instance)
(list (julia-image instance)
(julia-x instance)
(julia-y instance)
(julia-size instance)
(julia-ca instance)
(julia-cb instance)
(julia-progress instance)))
(update instance))
#<JUPYTER-WIDGETS:TRAIT-METACLASS COMMON-LISP-USER::JULIA-WIDGET>
CALCULATE-ROW
UPDATE
#<STANDARD-METHOD COMMON-LISP:INITIALIZE-INSTANCE :AFTER (JULIA-WIDGET) {100490DE93}>
(make-instance 'julia-widget)
A Jupyter Widget