[net.lang.prolog] FAIM, and Arrays

Shimon%SRI-KL@sri-unix.UUCP (07/26/84)

From:  Shimon Cohen <Shimon@SRI-KL>


1] I get more than a 100 (yes: one zero zero) requests
   for the working paper about the language for the FAIM
   machine. It will take a little while before we will
   send it to you. If you have sent only your electronic
   address it is not enough.

2] If you remember the debate we had about arrays in Prolog
   WELL I have looked closely into the algorithm by Kahn,
   if you recall when you update an array (in his method)
   you copy the entire list of changes. This copying is
   expensive both in time and place, but I think I can do it
   in constant time and place !  Namely, update will
   generate just one more element to add to the list.

Access is affected just a little bit by this
 NEW, IMPROVED, SUPER, DUPER, EXTRA method ...

It preserves the property of the old algorithm: Old unreferenced
versions are left to the mercy of the GC.  Also access time for the
most new version is also constant.  The only thing is that I am still
checking if there are no bugs, if you are interested try it yourself
and report any bugs to me (THANKS)

-- Shimon Cohen


(the code for the Symbolics 3600 follows)

; ; for the benefit of portability I will define an abstarct ;
data-type for element in the modification list.  ; ; The structure has
4 field:  ; index - of element chnaged ; value - of element ; next -
in list to escape ; next-skip - skip this element in your search ; qn
- query number ; (defstruct (new-element :conc-name (:type
:named-array))
    index value next next-skip (qn 0))


(defmacro get-index (e) (list 'aref e 1)) (defmacro get-value (e)
(list 'aref e 2)) (defmacro get-next (e) (list 'aref e 3)) (defmacro
get-next-skip (e) (list 'aref e 4)) (defmacro get-qn (e) (list 'aref e
5))

(defmacro set-index (e x) `(aset ,x ,e 1)) (defmacro set-value (e x)
`(aset ,x ,e 2)) (defmacro set-next (e x) `(aset ,x ,e 3)) (defmacro
set-next-skip (e x) `(aset ,x ,e 4)) (defmacro set-qn (e x) `(aset ,x
,e 5))

(defmacro new-physical-mva (a e) `(cons ,a ,e))

(defun new-last-element (ae)
     (prog (newe newe)
           (setq newe (make-new-element))
           (set-qn newe (get-qn (cdr ae)))
           (set-next (cdr ae) newe)
           (rplacd ae newe)
           (return newe) ))


(defmacro get-last-element (ae) (list 'cdr ae)) (defmacro
get-physical-array (ae) (list 'car ae))

(defstruct (mva-pointer :conc-name (:type :named-array))
     pa-le last-ele list-changes)

(defmacro get-pa-le (aee) `(aref ,aee 1)) (defmacro get-last-ele (aee)
`(aref ,aee 2)) (defmacro get-list-changes (aee) `(aref ,aee 3))

(defun new-mva-pointer (p e l)
  (prog (x)
        (setq x (make-mva-pointer ))
        (aset p x 1)
        (aset e x 2)
        (aset l x 3)
        (return x)))


(defun new-mva (size)
   (prog (a e ae)
         (setq a (make-array size))
         (setq e (make-new-element ))
         (setq ae (new-physical-mva a e))
         (return (new-mva-pointer ae nil (cdr ae))) ))

(defun update-mva (mva i v)
         (prog (ae e pmva laste newlaste)
               (setq ae (get-pa-le mva))
               (setq pmva (get-physical-array ae)) ; pmva the physical
mva
               (setq laste (get-last-element ae))
                     ; last ele. now will hold modification
               (setq e (get-last-ele mva))
               (set-index laste i)
               (set-value laste (aref pmva i)) ; store value
               (aset v pmva i) ; update (in zeta-lisp)
               (setq newlaste (new-last-element ae) ); create new
element
               (set-next-skip laste e )
               (return (if (eq laste (get-list-changes mva))
                           (new-mva-pointer ae nil newlaste)
                           (new-mva-pointer ae laste (get-list-changes
mva))
                           ))
               ))

(defun ref-mva (mva i)
  (prog (ae e pmva x laste flag )
        (setq ae (get-pa-le mva))
        (setq pmva (get-physical-array ae)) ; pmva the physical mva
        (setq laste (get-last-element ae)) ; last ele. now hold
modification
        (setq e (get-last-ele mva)) ; to skip
        (set-qn laste (setq qn (1+ (get-qn laste)))) ; incr. query
number
        (loop while (and e (neq i (get-index e)))
              do (set-qn e qn)
              do (setq e (get-next-skip e))
                                                ; do (describe e)
              )
        (loop initially (setq x (if e (get-next e) (get-list-changes
mva)))
              while (neq x laste)
              do (if (and (eq i (get-index x)) (neq qn (get-qn x)))
                           (return (setq flag t))
                           (setq x (get-next x))
                           ))
        (return (if flag (get-value x) (aref pmva i)))
        ))

(defvar x nil) (defvar a nil) (defvar b nil) (defvar c nil) (defvar d
nil) (defvar e nil) (defvar f nil) (defvar g nil) (defvar h nil) 
(defvar i nil) (defun test ()
  (prog ()
         (setq a (new-mva 10))
         (setq b (update-mva a 1 'b))
         (setq c (update-mva b 3 'c))
         (setq d (update-mva c 3 'd))
         (setq e (update-mva d 2 'e))
         (setq f (update-mva d 1 'f))
         (setq g (update-mva c 2 'g))
         (setq h (update-mva f 2 'h))
         (setq i (update-mva g 1 'i))
         (setq x (list a b c d e f g h))
         (return x)
         ))