Matrix相关源码

矩阵的数据结构其实是个一维数组:0、1、2代表第一行,3、4、5代表第二行,6、7、8代表第三行,如下:
[0, 1, 2,
 3, 4, 5,
 6, 7, 8]


每个位置代表的值:
[scaleX,       skewX,        translateX,           //第一行为x方向的值
 skewY,        scaleY,       translateY,             //第二行为y方向的值
 perspective0, perspective1, perspective2]         //第三行为透视相关值

[横向缩放因子,  横向扭曲因子,   横向位移,
 竖向扭曲因子,  竖向缩放因子,   竖向位移,
 x轴透视因子,   y轴透视因子,   透视因子]
 

preTranslate 和 postTranslate 的区别不仅仅是右乘和左乘,native层源码如下。

//矩阵的数据结构其实是个一维数组:0、1、2代表第一行,3、4、5代表第二行,6、7、8代表第三行,
//[0, 1, 2,
// 3, 4, 5,
// 6, 7, 8]
//
//[scaleX,       skewX,        translateX,           //第一行为x方向的值
// skewY,        scaleY,       translateY,			 //第二行为y方向的值
// perspective0, perspective1, perspective2]		 //第三行为透视相关值
//
//[横向缩放因子,  横向扭曲因子,   横向位移,
// 竖向扭曲因子,  竖向缩放因子,   竖向位移,
// x轴透视因子,   y轴透视因子,   透视因子]


enum {
    kMScaleX, //!< horizontal scale factor
    kMSkewX,  //!< horizontal skew factor
    kMTransX, //!< horizontal translation
    kMSkewY,  //!< vertical skew factor
    kMScaleY, //!< vertical scale factor
    kMTransY, //!< vertical translation
    kMPersp0, //!< input x perspective factor
    kMPersp1, //!< input y perspective factor
    kMPersp2, //!< perspective bias
};




enum TypeMask {
    kIdentity_Mask    = 0,    //!< all bits clear if SkMatrix is identity
    kTranslate_Mask   = 0x01, //!< set if SkMatrix has translation
    kScale_Mask       = 0x02, //!< set if SkMatrix has x or y scale
    kAffine_Mask      = 0x04, //!< set if SkMatrix skews or rotates
    kPerspective_Mask = 0x08, //!< set if SkMatrix has perspective
};

static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
    return a * b + c * d;
}


void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
    const unsigned mask = this->getType();

    if (mask <= kTranslate_Mask) {
    	//如果当前矩阵没有过变化,或者只有translate的变化
        fMat[kMTransX] += dx;
        fMat[kMTransY] += dy;
    } else if (mask & kPerspective_Mask) {
    	//如果当前矩阵有透视的变化
        SkMatrix    m;
        m.setTranslate(dx, dy);
        this->preConcat(m);
        return;
    } else {
    	//有 缩放 或者 扭曲
        fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
        fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
    }
    this->updateTranslateMask();
}



void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
    if (this->hasPerspective()) {
    	//如果当前矩阵有透视
        SkMatrix    m;
        m.setTranslate(dx, dy);
        this->postConcat(m);
    } else {
    	
        fMat[kMTransX] += dx;
        fMat[kMTransY] += dy;
        this->updateTranslateMask();
    }
}


void SkMatrix::preConcat(const SkMatrix& mat) {
    // check for identity first, so we don't do a needless copy of ourselves
    // to ourselves inside setConcat()
    if(!mat.isIdentity()) {
        this->setConcat(*this, mat);
    }
}

void SkMatrix::postConcat(const SkMatrix& mat) {
    // check for identity first, so we don't do a needless copy of ourselves
    // to ourselves inside setConcat()
    if (!mat.isIdentity()) {
        this->setConcat(mat, *this);
    }
}

static inline float SkDoubleToFloat(double x) {
    return static_cast<float>(x);
}


static inline float muladdmul(float a, float b, float c, float d) {
    return SkDoubleToFloat((double)a * b + (double)c * d);
}

/**
* 参数为地址,c++操作: 地址[n] = 向后寻址n位
**/
static inline float rowcol3(const float row[], const float col[]) {
    return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
}

static bool only_scale_and_translate(unsigned mask) {
    return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask));
}



/**
* 合并矩阵
**/
void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
    TypeMask aType = a.getType();
    TypeMask bType = b.getType();

    if (a.isTriviallyIdentity()) {
    	//a矩阵没有改变过
        *this = b;
    } else if (b.isTriviallyIdentity()) {
    	//b矩阵没有改变过
        *this = a;
    } else if (only_scale_and_translate(aType | bType)) {
    	//只有缩放和位移
        this->setScaleTranslate(a.fMat[kMScaleX] * b.fMat[kMScaleX],
                                a.fMat[kMScaleY] * b.fMat[kMScaleY],
                                a.fMat[kMScaleX] * b.fMat[kMTransX] + a.fMat[kMTransX],
                                a.fMat[kMScaleY] * b.fMat[kMTransY] + a.fMat[kMTransY]);
    } else {
        SkMatrix tmp;

        if ((aType | bType) & kPerspective_Mask) {
        	//矩阵乘法,x行 与 y列的乘积的和为结果矩阵的的 x行y列位置
            tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]);
            tmp.fMat[kMSkewX]  = rowcol3(&a.fMat[0], &b.fMat[1]);
            tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]);
            tmp.fMat[kMSkewY]  = rowcol3(&a.fMat[3], &b.fMat[0]);
            tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]);
            tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]);
            tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]);
            tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]);
            tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]);

            normalize_perspective(tmp.fMat);
            tmp.setTypeMask(kUnknown_Mask);
        } else {
            tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX],
                                           b.fMat[kMScaleX],
                                           a.fMat[kMSkewX],
                                           b.fMat[kMSkewY]);

            tmp.fMat[kMSkewX]  = muladdmul(a.fMat[kMScaleX],
                                           b.fMat[kMSkewX],
                                           a.fMat[kMSkewX],
                                           b.fMat[kMScaleY]);

            tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX],
                                           b.fMat[kMTransX],
                                           a.fMat[kMSkewX],
                                           b.fMat[kMTransY]) + a.fMat[kMTransX];

            tmp.fMat[kMSkewY]  = muladdmul(a.fMat[kMSkewY],
                                           b.fMat[kMScaleX],
                                           a.fMat[kMScaleY],
                                           b.fMat[kMSkewY]);

            tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY],
                                           b.fMat[kMSkewX],
                                           a.fMat[kMScaleY],
                                           b.fMat[kMScaleY]);

            tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY],
                                           b.fMat[kMTransX],
                                           a.fMat[kMScaleY],
                                           b.fMat[kMTransY]) + a.fMat[kMTransY];

            tmp.fMat[kMPersp0] = 0;
            tmp.fMat[kMPersp1] = 0;
            tmp.fMat[kMPersp2] = 1;
            //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
            //SkASSERT(!(tmp.getType() & kPerspective_Mask));
            tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
        }
        *this = tmp;
    }
}








   源码位置:

/external/skia/include/core/SkMatrix.h

 /external/skia/src/core/SkMatrix.cpp

 /frameworks/base/core/jni/android/graphics/Matrix.cpp

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
csc_matrix是SciPy中的一个稀疏矩阵格式,它使用压缩列存储格式(Compressed Sparse Column)来表示稀疏矩阵。下面是csc_matrix包的源码: ```python class csc_matrix(spmatrix): def __init__(self, arg1, shape=None, dtype=None, copy=False): _data_matrix.__init__(self) if isspmatrix_csc(arg1): if issubclass(arg1.__class__, self.__class__) and copy: arg1 = arg1.copy() self._set_self(arg1) return if dtype is None: dtype = getdtype(float, arg1) from .coo import coo_matrix if isspmatrix(arg1): if shape is None: shape = arg1.shape self._set_self(self.__class__((arg1.data, arg1.indices, arg1.indptr), shape=shape, dtype=dtype, copy=copy)) return if shape is None: try: shape = arg1.shape except AttributeError: raise TypeError('expected dimension') if isintlike(arg1): n = int(arg1) self._shape = (n,n) self._check() return if isshape(arg1): self._shape = tuple(arg1) self._check() return # Now we must have something that we can convert to a csc_matrix # First convert to coo try: arg1 = coo_matrix(arg1, dtype=dtype).tocsc() except TypeError: raise ValueError("unrecognized format: {!r}".format(arg1)) self._set_self(arg1) def _get_row_slice(self, i, cslice): if i < 0: M,N = self.shape i += M if cslice.step not in (1, None): raise ValueError('slicing with step != 1 not supported') start, stop = cslice.start, cslice.stop if start is None: start = 0 if stop is None: stop = self.shape[1] if i < 0 or i >= self.shape[0]: raise IndexError('index out of bounds') if stop <= start: return array(self.dtype) indptr = self.indptr indices = self.indices startptr, stopptr = indptr[i], indptr[i+1] start_idx = searchsorted(indices[startptr:stopptr], start) stop_idx = searchsorted(indices[startptr:stopptr], stop) if indices[startptr+stop_idx-1] != stop: stop_idx = stop_idx - 1 num_indices = stop_idx - start_idx if num_indices == 0: return array(self.dtype) idx_dtype = get_index_dtype((indices, indptr), maxval=max(self.shape)) row_data = np.empty(num_indices, dtype=self.dtype) row_indices = np.empty(num_indices, dtype=idx_dtype) row_data[:] = self.data[startptr+start_idx: startptr+stop_idx] row_indices[:] = indices[startptr+start_idx:startptr+stop_idx] return csc_matrix((row_data, row_indices, np.array([0, num_indices], dtype=idx_dtype)), shape=(1, stop-start), dtype=self.dtype) def _get_col_slice(self, j, rslice): if j < 0: M,N = self.shape j += N if rslice.step not in (1, None): raise ValueError('slicing with step != 1 not supported') start, stop = rslice.start, rslice.stop if start is None: start = 0 if stop is None: stop = self.shape[0] if j < 0 or j >= self.shape[1]: raise IndexError('index out of bounds') if stop <= start: return array(self.dtype) indptr = self.indptr indices = self.indices data = self.data i0 = searchsorted(indptr, j, side='left') i1 = searchsorted(indptr, j+1, side='left') idx_dtype = get_index_dtype((indices, indptr), maxval=self.shape[0]) row_indices = np.empty(i1-i0, dtype=idx_dtype) row_data = np.empty(i1-i0, dtype=self.dtype) row_indices = indices[i0:i1] row_data = data[i0:i1] mask = (row_indices >= start) & (row_indices < stop) row_indices = row_indices[mask] - start return csc_matrix((row_data[mask], row_indices, np.array([0,len(row_indices)], dtype=idx_dtype)), shape=(stop-start, 1), dtype=self.dtype) def _mul_scalar(self, other): return self.__class__((self.data * other, self.indices.copy(), self.indptr.copy()), shape=self.shape, dtype=self.dtype) def _mul_vector(self, other): M, N = self.shape if other.shape != (N,): raise ValueError("dimension mismatch") result = np.zeros(M, dtype=upcast_char(self.dtype.char, other.dtype.char)) fn = getattr(_sparsetools, self.format + '_vec_mul') fn(M, N, self.indptr, self.indices, self.data, other, result) return result def _mul_multimatrix(self, other): M, K = self.shape _, N = other.shape result = spmatrix(dtype=self.dtype, shape=(M,N)) o_data = other.data if isspmatrix(other): fn = getattr(_sparsetools, self.format + '_matmat_pass1') fn(M, K, N, self.indptr, self.indices, other.indptr, other.indices, o_data) fn = getattr(_sparsetools, self.format + '_matmat_pass2') fn(M, K, N, self.indptr, self.indices, self.data, other.indptr, other.indices, o_data, result.indptr, result.indices) else: fn = getattr(_sparsetools, self.format + '_matvec') for j in range(N): fn(M, K, self.indptr, self.indices, self.data, o_data[:,j], result.data, j) result.sum_duplicates() return result def _get_dense(self, i, j): # Short-circuit zero case if self.nnz == 0: return np.zeros(self.shape, dtype=self.dtype)[i, j] M, N = self.shape if i < 0: i += M if j < 0: j += N if i < 0 or i >= M or j < 0 or j >= N: raise IndexError("index out of bounds") indptr = self.indptr indices = self.indices data = self.data i0 = indptr[j] i1 = indptr[j+1] if i0 == i1: return 0 idx = searchsorted(indices[i0:i1], i) + i0 if idx == i1 or indices[idx] != i: return 0 return data[idx] def _get_sparse(self, i, j): from . import lil_matrix M, N = self.shape if i < 0: i += M if j < 0: j += N if i < 0 or i >= M or j < 0 or j >= N: raise IndexError("index out of bounds") indptr = self.indptr indices = self.indices i0 = indptr[j] i1 = indptr[j+1] data = self.data[i0:i1] indices = indices[i0:i1] indptr = np.array([0, len(data)], dtype=idx_dtype) return lil_matrix((data, indices, indptr), shape=(1, N)) def __eq__(self, other): return self._eq_dense(other) def diagonal(self, k=0): if self.shape[0] != self.shape[1]: raise ValueError("diagonal is only defined for square matrices") if k > 0: n = self.shape[1] - k indptr = self.indptr[k:] indices = self.indices[indptr[0]:indptr[-1]] data = self.data[indptr[0]:indptr[-1]] else: n = self.shape[0] + k indptr = self.indptr[:n+1] indices = self.indices[indptr[0]:indptr[-1]] data = self.data[indptr[0]:indptr[-1]] return csc_matrix((data, indices, indptr), shape=(n,n)) def sum(self, axis=None, dtype=None, out=None): if dtype is not None and not np.issubdtype(dtype, self.dtype): raise TypeError('Cannot upcast [%s] to [%s].' % (self.dtype, dtype)) if axis is None: return np.asarray(self.data.sum(dtype=dtype), dtype=dtype) elif axis == 0: if out is not None: raise ValueError("output array specified for reductions along axis 0,\ but unsupported for csc_matrix") ret = np.empty(self.shape[1], dtype=dtype) for i in range(self.shape[1]): ret[i] = self.getcol(i).sum(dtype=dtype) return ret elif axis == 1: if out is not None: raise ValueError("output array specified for reductions along axis 1,\ but unsupported for csc_matrix") ret = np.empty(self.shape[0], dtype=dtype) for i in range(self.shape[0]): ret[i] = self.getrow(i).sum(dtype=dtype) return ret else: raise ValueError("axis out of bounds") ``` csc_matrix的实现主要基于COO格式,因为COO格式在行和列的切片操作上比较高效。除此之外,该源代码还实现了csc_matrix的加、减、乘、除、取负、转置、切片、求逆、求行列式、求特征值和特征向量等方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值