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.
8 "gonum.org/v1/gonum/blas/blas64"
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"
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"
20 // mismatchedStrides is the panic string used for overlapping
21 // data slices with differing strides.
22 mismatchedStrides = "mat: bad region: different strides"
25 // checkOverlap returns false if the receiver does not overlap data elements
26 // referenced by the parameter and panics otherwise.
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 {
35 off := offset(a.Data[:1], b.Data[:1])
38 // At least one element overlaps.
39 if a.Cols == b.Cols && a.Rows == b.Rows && a.Stride == b.Stride {
45 if off > 0 && len(a.Data) <= off {
46 // We know a is completely before b.
49 if off < 0 && len(b.Data) <= -off {
50 // We know a is completely after b.
54 if a.Stride != b.Stride {
55 // Too hard, so assume the worst.
56 panic(mismatchedStrides)
61 a.Cols, b.Cols = b.Cols, a.Cols
63 if rectanglesOverlap(off, a.Cols, b.Cols, a.Stride) {
69 func (m *Dense) checkOverlap(a blas64.General) bool {
70 return checkOverlap(m.RawMatrix(), a)
73 func (s *SymDense) checkOverlap(a blas64.General) bool {
74 return checkOverlap(generalFromSymmetric(s.RawSymmetric()), a)
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{
88 func (t *TriDense) checkOverlap(a blas64.General) bool {
89 return checkOverlap(generalFromTriangular(t.RawTriangular()), a)
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{
103 func (v *VecDense) checkOverlap(a blas64.Vector) bool {
105 if cap(mat.Data) == 0 || cap(a.Data) == 0 {
109 off := offset(mat.Data[:1], a.Data[:1])
112 // At least one element overlaps.
113 if mat.Inc == a.Inc && len(mat.Data) == len(a.Data) {
114 panic(regionIdentity)
119 if off > 0 && len(mat.Data) <= off {
120 // We know v is completely before a.
123 if off < 0 && len(a.Data) <= -off {
124 // We know v is completely after a.
128 if mat.Inc != a.Inc {
129 // Too hard, so assume the worst.
130 panic(mismatchedStrides)
133 if mat.Inc == 1 || off&mat.Inc == 0 {
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.
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 {
150 // Unit stride means overlapping data
151 // slices must overlap as matrices.
155 // Flatten the shifted matrix column positions
156 // so a starts at 0, modulo the common stride.
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
164 if bTo == 0 || bFrom < bTo {
165 // b matrix is not wrapped: compare for
170 // b strictly wraps and so must overlap with a.