OSDN Git Service

test (#52)
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / mat / shadow.go
1 // Copyright ©2015 The Gonum Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package mat
6
7 import (
8         "gonum.org/v1/gonum/blas/blas64"
9 )
10
11 const (
12         // regionOverlap is the panic string used for the general case
13         // of a matrix region overlap between a source and destination.
14         regionOverlap = "mat: bad region: overlap"
15
16         // regionIdentity is the panic string used for the specific
17         // case of complete agreement between a source and a destination.
18         regionIdentity = "mat: bad region: identical"
19
20         // mismatchedStrides is the panic string used for overlapping
21         // data slices with differing strides.
22         mismatchedStrides = "mat: bad region: different strides"
23 )
24
25 // checkOverlap returns false if the receiver does not overlap data elements
26 // referenced by the parameter and panics otherwise.
27 //
28 // checkOverlap methods return a boolean to allow the check call to be added to a
29 // boolean expression, making use of short-circuit operators.
30 func checkOverlap(a, b blas64.General) bool {
31         if cap(a.Data) == 0 || cap(b.Data) == 0 {
32                 return false
33         }
34
35         off := offset(a.Data[:1], b.Data[:1])
36
37         if off == 0 {
38                 // At least one element overlaps.
39                 if a.Cols == b.Cols && a.Rows == b.Rows && a.Stride == b.Stride {
40                         panic(regionIdentity)
41                 }
42                 panic(regionOverlap)
43         }
44
45         if off > 0 && len(a.Data) <= off {
46                 // We know a is completely before b.
47                 return false
48         }
49         if off < 0 && len(b.Data) <= -off {
50                 // We know a is completely after b.
51                 return false
52         }
53
54         if a.Stride != b.Stride {
55                 // Too hard, so assume the worst.
56                 panic(mismatchedStrides)
57         }
58
59         if off < 0 {
60                 off = -off
61                 a.Cols, b.Cols = b.Cols, a.Cols
62         }
63         if rectanglesOverlap(off, a.Cols, b.Cols, a.Stride) {
64                 panic(regionOverlap)
65         }
66         return false
67 }
68
69 func (m *Dense) checkOverlap(a blas64.General) bool {
70         return checkOverlap(m.RawMatrix(), a)
71 }
72
73 func (s *SymDense) checkOverlap(a blas64.General) bool {
74         return checkOverlap(generalFromSymmetric(s.RawSymmetric()), a)
75 }
76
77 // generalFromSymmetric returns a blas64.General with the backing
78 // data and dimensions of a.
79 func generalFromSymmetric(a blas64.Symmetric) blas64.General {
80         return blas64.General{
81                 Rows:   a.N,
82                 Cols:   a.N,
83                 Stride: a.Stride,
84                 Data:   a.Data,
85         }
86 }
87
88 func (t *TriDense) checkOverlap(a blas64.General) bool {
89         return checkOverlap(generalFromTriangular(t.RawTriangular()), a)
90 }
91
92 // generalFromTriangular returns a blas64.General with the backing
93 // data and dimensions of a.
94 func generalFromTriangular(a blas64.Triangular) blas64.General {
95         return blas64.General{
96                 Rows:   a.N,
97                 Cols:   a.N,
98                 Stride: a.Stride,
99                 Data:   a.Data,
100         }
101 }
102
103 func (v *VecDense) checkOverlap(a blas64.Vector) bool {
104         mat := v.mat
105         if cap(mat.Data) == 0 || cap(a.Data) == 0 {
106                 return false
107         }
108
109         off := offset(mat.Data[:1], a.Data[:1])
110
111         if off == 0 {
112                 // At least one element overlaps.
113                 if mat.Inc == a.Inc && len(mat.Data) == len(a.Data) {
114                         panic(regionIdentity)
115                 }
116                 panic(regionOverlap)
117         }
118
119         if off > 0 && len(mat.Data) <= off {
120                 // We know v is completely before a.
121                 return false
122         }
123         if off < 0 && len(a.Data) <= -off {
124                 // We know v is completely after a.
125                 return false
126         }
127
128         if mat.Inc != a.Inc {
129                 // Too hard, so assume the worst.
130                 panic(mismatchedStrides)
131         }
132
133         if mat.Inc == 1 || off&mat.Inc == 0 {
134                 panic(regionOverlap)
135         }
136         return false
137 }
138
139 // rectanglesOverlap returns whether the strided rectangles a and b overlap
140 // when b is offset by off elements after a but has at least one element before
141 // the end of a. off must be positive. a and b have aCols and bCols respectively.
142 //
143 // rectanglesOverlap works by shifting both matrices left such that the left
144 // column of a is at 0. The column indexes are flattened by obtaining the shifted
145 // relative left and right column positions modulo the common stride. This allows
146 // direct comparison of the column offsets when the matrix backing data slices
147 // are known to overlap.
148 func rectanglesOverlap(off, aCols, bCols, stride int) bool {
149         if stride == 1 {
150                 // Unit stride means overlapping data
151                 // slices must overlap as matrices.
152                 return true
153         }
154
155         // Flatten the shifted matrix column positions
156         // so a starts at 0, modulo the common stride.
157         aTo := aCols
158         // The mod stride operations here make the from
159         // and to indexes comparable between a and b when
160         // the data slices of a and b overlap.
161         bFrom := off % stride
162         bTo := (bFrom + bCols) % stride
163
164         if bTo == 0 || bFrom < bTo {
165                 // b matrix is not wrapped: compare for
166                 // simple overlap.
167                 return bFrom < aTo
168         }
169
170         // b strictly wraps and so must overlap with a.
171         return true
172 }