Coverage report: /development/source/library/org/datagraph/spocq-shard/src/algebra/matrix-operators/extend.lisp

KindCoveredAll%
expression0156 0.0
branch08 0.0
Key
Not instrumented
Conditionalized out
Executed
Not executed
 
Both branches taken
One branch taken
Neither branch taken
1
 ;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
2
 
3
 (in-package :org.datagraph.spocq.implementation)
4
 
5
 (:documentation "sparql slice operation for matrix fields")
6
 
7
 ;;; (load (compile-file "/development/source/library/org/datagraph/spocq/src/algebra/matrix-operators/slice.lisp"))
8
 
9
 (defmethod spocq.e:extend ((source-field matrix-field) bindings &rest arguments &key start end)
10
   (declare (dynamic-extent arguments))
11
   (let* ((base-dimensions (matrix-field-dimensions source-field))
12
          (length (- (or end (field-length source-field)) (or start 0)))
13
          (result-dimensions (loop for binding in bindings
14
                                   collect (if (consp binding) (first binding) binding)))
15
          (width (length result-dimensions))
16
          (%data (rdfcache:make-matrix length width))
17
          (result-field (clone-matrix-field source-field :data %data
18
                                            :dimensions result-dimensions
19
                                            :sort-dimensions (loop for dimension in (matrix-field-sort-dimensions source-field)
20
                                                                   when (find dimension result-dimensions)
21
                                                                   collect dimension)))
22
          (operator (apply #'matrix-extend-operator result-dimensions base-dimensions
23
                           (loop for binding in bindings
24
                                 when (consp binding)
25
                                 collect binding)
26
                           arguments)))
27
       (apply operator result-field source-field
28
              arguments)
29
       result-field))
30
 
31
 
32
 (defmethod process-extend ((destination matrix-page-channel)
33
                            (source matrix-page-channel)
34
                            result-dimensions base-dimensions bindings
35
                            &key offset count
36
                                 (start offset)
37
                                 (end (when count (+ count (or start 0)))))
38
   (declare (ignore start end))
39
   (let ((operator (matrix-extend-operator result-dimensions base-dimensions bindings)))
40
     (funcall operator destination source
41
              :start start :end end))
42
   (values (channel-solution-count destination)
43
           (channel-solution-count source)))
44
 
45
 
46
 ;;;!!! still need to abstract the extend operator
47
 ;;; first cache any computed values - if there is an error, skip
48
 ;;; then perform a term-number projection, computed from the result side to move just the identity values 
49
 ;;; then move the computed values
50
 
51
 (defun matrix-extend-operator (result-dimensions source-dimensions bindings &rest args)
52
   (declare (dynamic-extent args))
53
 
54
   (let* ((bindings-dimensions (bindings-variables bindings))
55
          (rebound-variables (intersection bindings-dimensions source-dimensions)))
56
     (when *strict-extend-bindings*
57
       ;; See [http://www.w3.org/TR/sparql11-query/#sparqlGrammar] wrt restrictions.
58
       (assert (null rebound-variables) ()
59
               "The variables are already bound: ~a" rebound-variables))
60
     (let* ((projection (loop for source-dimension in source-dimensions
61
                              collect (when source-dimension (position source-dimension result-dimensions))))
62
            (all-dimensions (union-dimensions (union-dimensions result-dimensions source-dimensions) bindings-dimensions))
63
            (dimension-map (loop for count from 0
64
                                 for dimension in all-dimensions
65
                                 collect (cons dimension (cons-symbol *variable-package* "v" (princ-to-string count)))))
66
            (generic-result-dimensions (sublis dimension-map result-dimensions))
67
            (generic-source-dimensions (sublis dimension-map source-dimensions))
68
            (generic-bindings (sublis dimension-map bindings)))
69
       (values (ensure-matrix-operator 'extend :projection projection
70
                                       :source-dimensions generic-source-dimensions
71
                                       :result-dimensions generic-result-dimensions
72
                                       :bindings generic-bindings
73
                                       :slice (not (null args)))
74
               result-dimensions))))
75
 
76
     
77
 (defmethod compute-matrix-operator-lambda ((operator (eql 'extend))
78
                                            &key projection source-dimensions result-dimensions bindings slice)
79
   (let* ((source-column-count (length projection))
80
          (result-column-count (length result-dimensions))
81
          (referenced-dimensions (expression-variables (mapcar #'rest bindings))))
82
     `(lambda (result-field source-field ,@(when slice '(&key (start 0) end)))
83
        ,(format nil "extend operator for projection: ~s; extension: ~s." projection bindings)
84
        (declare (type matrix-field result-field source-field)
85
                 (optimize ,@*field-optimization*)
86
                 ,@(when slice '((type fixnum start))))
87
        
88
        (unless (= (channel-page-width result-field) ,result-column-count) ()
89
                (matrix-dimension-error :matrix result-field :expected-dimensions '(* ,result-column-count)))
90
        (unless (= (channel-page-width source-field) ,source-column-count) ()
91
                (matrix-dimension-error :matrix source-field :expected-dimensions '(* ,source-column-count)))
92
        (incf-stat *algebra-operations*)
93
        
94
        (let ((%source-data (cffi::null-pointer))
95
              (%result-data (cffi::null-pointer))
96
              (source-row 0)
97
              (result-row 0))
98
          (declare (foreign-type (foreign-array ,+matrix-element-type+ (* ,source-column-count)) %source-data)
99
                   (foreign-type (foreign-array ,+matrix-element-type+ (* ,result-column-count)) %result-data)
100
                   (type sb-sys:system-area-pointer %source-data %result-data)
101
                   (type fixnum source-row result-row)
102
                   )
103
          (handler-bind ((error (lambda (c)
104
                                  (log-trace "extend raised condition: ~a" c)
105
                                  (throw :skip nil))))
106
            (loop ,@(when slice '(with result-count fixnum = 0 until (and end (>= result-count (the fixnum end)))))
107
                  until (cffi:null-pointer-p (setf (values %source-data source-row) (next-field-row source-field)))
108
                  ,@(when slice '(when (> (incf result-count) start)))
109
                  do (let ,(loop for variable in referenced-dimensions
110
                                  for position = (position variable source-dimensions)
111
                                  collect (list variable `(foreign-array-named-object-ref ,variable %source-data source-row ,position)))
112
                        (catch :skip
113
                          (let* ,(loop for (variable expression) in bindings
114
                                       collect `(,variable (locally (declare (optimize (speed 0) (safety 3))) ,expression)))
115
                            ;; when the extension computation succeeds
116
                            (setf (values %result-data result-row) (new-field-row result-field))
117
                            (trace-matrix "~&extend.next-result ~@{~a ~}" :source source-row :result result-row
118
                                          ,@(when slice '(:result-count result-count)))
119
                            ,@(loop for variable in source-dimensions
120
                                    for source-position from 0
121
                                    for result-position = (position variable result-dimensions)
122
                                    when result-position
123
                                    collect `(setf (foreign-array-ref %result-data result-row ,result-position)
124
                                                   (foreign-array-ref %source-data source-row ,source-position)))
125
                            ,@(loop for (variable nil) in bindings
126
                                    for result-position = (position variable result-dimensions)
127
                                    collect `(setf (foreign-array-named-object-ref ,variable %result-data result-row ,result-position) ,variable)))))))
128
          (complete-field result-field)
129
          result-field))))
130
 
131
 
132
 ;;; (spocq-compile (compute-matrix-operator-lambda 'extend :projection '(1 nil 3 2) :result-dimensions '(?::a ?::d ?::q ?::s) :source-dimensions '(?::a ?::s ?::d) :bindings '((?::q (spocq.a:+ ?::a ?::s))) :slice t))