|
43 | 43 | "The default prototype for a virtual array is 0."
|
44 | 44 | 0)
|
45 | 45 |
|
46 |
| -(defmethod etype-of ((varray varray)) |
47 |
| - "The default element type for a virtual array is T." |
48 |
| - 't) |
| 46 | +(defmethod etype-of ((item t)) |
| 47 | + "A literal array's element type is returned by the (array-element-type) function." |
| 48 | + (assign-element-type item)) |
49 | 49 |
|
50 | 50 | (defmethod etype-of ((array array))
|
51 | 51 | "A literal array's element type is returned by the (array-element-type) function."
|
52 | 52 | (array-element-type array))
|
53 | 53 |
|
| 54 | +(defmethod etype-of ((varray varray)) |
| 55 | + "The default element type for a virtual array is T." |
| 56 | + 't) |
| 57 | + |
54 | 58 | (defmethod shape-of ((_ t))
|
55 | 59 | "Non-arrays have a nil shape."
|
56 | 60 | (declare (ignore _))
|
|
106 | 110 | output))
|
107 | 111 | (let ((output (make-array (shape-of varray) :element-type (etype-of varray))))
|
108 | 112 | (dotimes (i (array-total-size output))
|
109 |
| - (setf (row-major-aref output i) |
110 |
| - (funcall indexer i))) |
| 113 | + (let ((indexed (funcall indexer i))) |
| 114 | + (if indexed (setf (row-major-aref output i) indexed)))) |
111 | 115 | output))
|
112 | 116 | (funcall indexer 1))))
|
113 | 117 |
|
|
354 | 358 | (funcall base-indexer indexed))
|
355 | 359 | (prototype-of (vader-base varray))))))))
|
356 | 360 |
|
| 361 | +(defclass vader-expand (varray-derived vad-on-axis vad-with-io vad-with-argument vad-invertable) |
| 362 | + nil (:documentation "An expanded (as from [\ expand]) or compressed (as from [/ compress]) array.")) |
357 | 363 |
|
358 |
| -(defclass vader-meta-scalar-pass (varray-derived) nil) |
| 364 | +(defmethod prototype-of ((varray vader-expand)) |
| 365 | + (let ((indexer (indexer-of (vader-base varray)))) |
| 366 | + ;; TODO: remove-disclose when [⍴ shape] is virtually implemented |
| 367 | + (aplesque::make-empty-array (disclose (if (not (functionp indexer)) |
| 368 | + indexer ;; ←← remove |
| 369 | + (funcall (indexer-of (vader-base varray)) 0)))))) |
| 370 | + |
| 371 | +(defmethod shape-of ((varray vader-expand)) |
| 372 | + "The shape of an expanded or compressed array." |
| 373 | + ;; (print (list :vv (shape-of (vads-argument varray)))) |
| 374 | + (get-or-assign-shape |
| 375 | + varray |
| 376 | + (let* ((degrees-count (first (shape-of (vads-argument varray)))) |
| 377 | + (degrees (setf (vads-argument varray) |
| 378 | + (funcall (lambda (i) |
| 379 | + (if (arrayp i) |
| 380 | + i (vector i))) |
| 381 | + (render (vads-argument varray))))) |
| 382 | + (base-shape (copy-list (shape-of (vader-base varray)))) |
| 383 | + (base-rank (length base-shape)) |
| 384 | + (is-inverse (vads-inverse varray)) |
| 385 | + (axis (setf (vads-axis varray) |
| 386 | + (max 0 (- (if (eq :last (vads-axis varray)) |
| 387 | + base-rank (vads-axis varray)) |
| 388 | + (vads-io varray)))))) |
| 389 | + |
| 390 | + ;; (print (list :br degrees-count is-inverse base-shape base-rank axis (vads-axis varray) |
| 391 | + ;; (vader-base varray))) |
| 392 | + |
| 393 | + (cond ((and base-shape (zerop (reduce #'* base-shape))) |
| 394 | + ;; (print :ee) |
| 395 | + (if is-inverse |
| 396 | + (if (> axis (1- base-rank)) |
| 397 | + (error "This array does not have an axis ~a." axis) |
| 398 | + (if (or (not (arrayp degrees)) |
| 399 | + (or (not degrees-count) |
| 400 | + (= 1 degrees-count))) |
| 401 | + (loop :for d :in base-shape :for dx :from 0 |
| 402 | + :collect (if (= dx axis) (* d (disclose-unitary degrees)) d)) |
| 403 | + (if (not degrees-count) |
| 404 | + (loop :for d :below base-rank :for dx :from 0 |
| 405 | + :collect (if (= dx axis) 0 d)) |
| 406 | + (if (and degrees-count (/= degrees-count (nth axis base-shape))) |
| 407 | + (error "Compression degrees must equal size of array in dimension to compress.") |
| 408 | + (let ((output-size (loop :for d :below degrees-count |
| 409 | + :summing (if (not (arrayp degrees)) |
| 410 | + degrees (aref degrees d))))) |
| 411 | + (loop :for d :in base-shape :for dx :from 0 |
| 412 | + :collect (if (= dx axis) output-size d))))))) |
| 413 | + (if (or (not degrees-count) |
| 414 | + (= 1 degrees-count) |
| 415 | + (not (arrayp degrees))) |
| 416 | + (list (if (and (= 1 base-rank) |
| 417 | + (zerop (if (not (arrayp degrees)) |
| 418 | + degrees (aref degrees 0)))) |
| 419 | + 1 (abs (if (not (arrayp degrees)) |
| 420 | + degrees (aref degrees 0))))) |
| 421 | + (if (and (loop :for d :across degrees :always (zerop d)) |
| 422 | + (zerop (nth axis base-shape))) |
| 423 | + (if (= 1 base-rank) (list degrees-count) |
| 424 | + (loop :for d :in base-shape :for dx :from 0 |
| 425 | + :collect (if (= dx axis) degrees-count d))) |
| 426 | + (error "An empty array can only be expanded to a single negative degree ~a" |
| 427 | + "or to any number of empty dimensions."))))) |
| 428 | + ((and (not is-inverse) |
| 429 | + (or (and (not (arrayp degrees)) |
| 430 | + (zerop degrees)) |
| 431 | + (and degrees-count (= 1 degrees-count) |
| 432 | + (zerop (aref degrees 0))))) |
| 433 | + ;; (print :ff) |
| 434 | + (append (butlast base-shape) (list 0))) |
| 435 | + ((and (not base-shape) |
| 436 | + (not (arrayp degrees))) |
| 437 | + ;; (print :gg) |
| 438 | + (setf (vads-argument varray) (list (abs degrees)))) |
| 439 | + ((and is-inverse base-shape degrees-count (< 1 degrees-count) |
| 440 | + (nth axis base-shape) |
| 441 | + (/= degrees-count (nth axis base-shape))) |
| 442 | + (error "Attempting to replicate elements across array but ~a" |
| 443 | + "degrees are not equal to length of selected input axis.")) |
| 444 | + ((and (not is-inverse) |
| 445 | + base-shape (< 1 (reduce #'* base-shape)) |
| 446 | + (nth axis base-shape) |
| 447 | + (/= (or (and (arrayp degrees) |
| 448 | + (loop :for degree :across degrees :when (< 0 degree) |
| 449 | + :counting degree :into dcount :finally (return dcount))) |
| 450 | + degrees) |
| 451 | + (nth axis base-shape))) |
| 452 | + (error "Attempting to expand elements across array but ~a" |
| 453 | + "positive degrees are not equal to length of selected input axis.")) |
| 454 | + (t (let* ((degrees (if (and (arrayp degrees) |
| 455 | + (not (= 1 (length degrees)))) |
| 456 | + degrees (setf (vads-argument varray) |
| 457 | + (make-array (or (nth axis base-shape) 1) |
| 458 | + :element-type 'fixnum |
| 459 | + :initial-element (disclose-unitary degrees))))) |
| 460 | + (c-degrees (make-array (length degrees) |
| 461 | + :element-type 'fixnum :initial-element 0)) |
| 462 | + (ex-dim)) |
| 463 | + ;; (print (list :gg degrees c-degrees)) |
| 464 | + (if t ;; (or (not (arrayp degrees)) |
| 465 | + ;; (= 1 degrees-count)) |
| 466 | + ;; (setq ex-dim (* (nth axis base-shape) |
| 467 | + ;; (abs (disclose-unitary degrees)))) |
| 468 | + (loop :for degree :across degrees :for dx :from 0 |
| 469 | + :summing (max (abs degree) (if is-inverse 0 1)) :into this-dim |
| 470 | + :do (setf (aref c-degrees dx) this-dim) |
| 471 | + :finally (setq ex-dim this-dim))) |
| 472 | + ;; (print (list :ee ex-dim)) |
| 473 | + (loop :for dim :in (or base-shape '(1)) :for index :from 0 |
| 474 | + :collect (if (/= index axis) dim (* 1 ex-dim))))))))) |
| 475 | + |
| 476 | +(defmethod indexer-of ((varray vader-expand)) |
| 477 | + (let ((base-indexer (indexer-of (vader-base varray))) |
| 478 | + (indexer (indexer-expand (coerce (vads-argument varray) 'vector) |
| 479 | + (shape-of (vader-base varray)) |
| 480 | + (vads-axis varray) |
| 481 | + (vads-inverse varray)))) |
| 482 | + ;; (PRINT (LIST :ss (shape-of varray))) |
| 483 | + (lambda (index) |
| 484 | + ;; (print (list :iin base-indexer (funcall indexer index) indexer)) |
| 485 | + (if (not (functionp base-indexer)) |
| 486 | + (if (funcall indexer index) |
| 487 | + (disclose base-indexer)) |
| 488 | + (let ((indexed (funcall indexer index))) |
| 489 | + (if indexed (funcall base-indexer indexed))))))) |
| 490 | + |
| 491 | +;; (defclass vader-meta-scalar-pass (varray-derived) nil) |
359 | 492 |
|
360 | 493 | (defclass vader-turn (varray-derived vad-on-axis vad-with-io vad-with-argument)
|
361 | 494 | nil (:documentation "A rotated array as from the [⌽ rotate] function."))
|
|
0 commit comments