vex*_*exe 16 c opengl matrix linear-algebra
我一直在阅读很多关于这一点,我读的越多,我就越困惑.
我的理解:在行主要行连续存储在内存中,列主要列连续存储在内存中.因此,如果我们有一系列数字[1, ..., 9]并且我们想将它们存储在行主矩阵中,我们得到:
|1, 2, 3|
|4, 5, 6|
|7, 8, 9|
Run Code Online (Sandbox Code Playgroud)
而专栏(如果我错了,纠正我)是:
|1, 4, 7|
|2, 5, 8|
|3, 6, 9|
Run Code Online (Sandbox Code Playgroud)
这实际上是前一个矩阵的转置.
我的困惑:嗯,我没有看到任何区别.如果我们迭代两个矩阵(按第一个中的行和第二个中的列),我们将以相同的顺序覆盖相同的值:1, 2, 3, ..., 9
即使矩阵乘法是相同的,我们采用第一个连续元素并将它们与第二个矩阵列相乘.所以说我们有矩阵M:
|1, 0, 4|
|5, 2, 7|
|6, 0, 0|
Run Code Online (Sandbox Code Playgroud)
如果我们乘上一列,主要基质R用M,那就是R x M我们会得到:
|1*1 + 2*0 + 3*4, 1*5 + 2*2 + 3*7, etc|
|etc.. |
|etc.. |
Run Code Online (Sandbox Code Playgroud)
如果我们乘列矩阵主要C有M,那就是C x M采取的列C,而不是其行,我们得到完全来自相同的结果R x M
我真的很困惑,如果一切都一样,为什么这两个词甚至存在呢?我的意思是即使在第一个矩阵中R,我也可以查看行并将它们视为列...
我错过了什么吗?row-major与col-major实际上对我的矩阵数学意味着什么?我总是在我的线性代数课程中学到,我们将第一个矩阵中的行与第二个矩阵中的列相乘,如果第一个矩阵在列专业中,那会改变吗?我们现在必须将其列与第二个矩阵中的列相乘,就像我在我的示例中所做的那样,或者只是错了吗?
任何澄清真的很感激!
编辑:我遇到的另一个混乱的主要原因之一是GLM ...所以我将鼠标悬停在它的矩阵类型上并点击F12以查看它是如何实现的,在那里我看到一个矢量数组,所以如果我们有一个3x3矩阵我们有一个3个向量的数组.看看那些矢量的类型我看到'col_type'所以我假设这些矢量中的每一个都代表一个列,因此我们有一个列主系统吗?
好吧,我不知道说实话.我写了这个打印函数来比较我的翻译矩阵与glm的,我在最后一行看到glm中的翻译向量,而我的最后一列是...
这只会增加混乱.您可以清楚地看到glmTranslate矩阵中的每个向量代表矩阵中的一行.所以...这意味着矩阵是行主要的吗?我的矩阵怎么样?(我正在使用一个浮点数组[16])翻译值在最后一列,这是否意味着我的矩阵是列主要的,我现在不是吗?试图阻止头部旋转
thu*_*zas 12
如果愿意的话,我认为你将实现细节与用法混为一谈.
让我们从一个二维数组或矩阵开始:
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
Run Code Online (Sandbox Code Playgroud)
问题是计算机内存是一维字节数组.为了使我们的讨论更容易,让我们将单个字节分组为四个组,因此我们看起来像这样,(每个单独,+ - +表示一个字节,四个字节表示一个整数值(假设32位操作系统):
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
| | | | | | | | |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
\/ \ /
one byte one integer
low memory ------> high memory
Run Code Online (Sandbox Code Playgroud)
另一种表达方式
因此,问题是如何将二维结构(我们的矩阵)映射到这个一维结构(即存储器)上.有两种方法可以做到这一点.
行主顺序:按此顺序,我们先将第一行放入内存,然后放入第二行,依此类推.这样做,我们将在内存中有以下内容:
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Run Code Online (Sandbox Code Playgroud)使用此方法,我们可以通过执行以下算法找到数组的给定元素.假设我们想要访问数组的$ M_ {ij} $元素.如果我们假设我们有一个指向数组第一个元素的指针,比如说ptr知道列数nCol,那么我们可以通过以下方式找到任何元素:
$M_{ij} = i*nCol + j$
Run Code Online (Sandbox Code Playgroud)
要了解其工作原理,请考虑M_ {02}(即第一行,第三列 - 记住C基于零.
$M_{02} = 0*3 + 2 = 2
Run Code Online (Sandbox Code Playgroud)
所以我们访问数组的第三个元素.
列主要排序:按此顺序,我们先将第一列放入内存,然后放入第二列,依此类推.这样做我们将在内存中有以下内容:
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 4 | 7 | 2 | 5 | 8 | 3 | 6 | 9 |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Run Code Online (Sandbox Code Playgroud)因此,简短的答案 - 行主要和列主要格式描述了两个(或更高)维数阵列如何映射到一维内存数组.
希望这可以帮助.T.
让我们先来看代数;代数甚至没有“内存布局”和内容的概念。
从代数pov看,MxN实矩阵可作用于右侧的| R ^ N向量,并产生| R ^ M向量。
因此,如果您正在参加考试并且给出了MxN矩阵和| R ^ N向量,则可以通过简单的运算将它们相乘并得到结果-该结果是对还是错将不取决于您的教授所用的软件用于内部检查结果,使用列主布局或行主布局;它仅取决于您是否正确计算了矩阵的每一行与向量的(单)列的收缩率。
为了产生正确的输出,该软件将(无论采取何种方式)实质上必须像在考试中一样,将Matrix的每一行与列向量进行收缩。
因此,对齐列重大和软件使用行为主的布局软件之间的区别是不是它计算的,但只是如何。
更确切地说,关于布局单行与列向量的收缩,这些布局之间的差异只是确定
Where is the next element of the current row?
Run Code Online (Sandbox Code Playgroud)
就是这样。
为了向您展示如何在实践中召唤该列/行魔术:
您尚未使用“ c ++”标记您的问题,但是由于您提到了“ glm ”,因此我认为您可以与C ++相处。
在C ++的标准库中,有一个臭名昭著的野兽,称为valarray,除了其他棘手的功能之外,还具有operator[]的重载,其中之一可以带一个std::slice(本质上是很无聊的事情,仅由三个整数类型的数字组成)。
不过,这小块的东西可以满足按列访问主要存储或逐行访问的所有内容-它具有起点,长度和步幅-后者代表“到下一个铲斗的距离”。
行专业或列专业只是一种约定。没关系。C 使用行专业,Fortran 使用列。两者都有效。使用您的编程语言/环境中的标准。
如果您在存储在 colum major 中的矩阵上使用行主要寻址,则可能会得到错误的元素,读取数组的末尾等...
Row major: A(i,j) element is at A[j + i * n_columns]; <---- mixing these up will
Col major: A(i,j) element is at A[i + j * n_rows]; <---- make your code fubar
Run Code Online (Sandbox Code Playgroud)
(当然矩阵乘法的数学是一样的。)想象一下你有两个数组在内存中:
X = [x1, x2, x3, x4] Y = [y1, y2, y3, y4]
Run Code Online (Sandbox Code Playgroud)
如果矩阵存储在主列中,则 X、Y 和 X*Y 为:
IF COL MAJOR: [x1, x3 * [y1, y3 = [x1y1+x3y2, x1y3+x3y4
x2, x4] y2, y4] x2y1+x4y2, x2y3+x4y4]
Run Code Online (Sandbox Code Playgroud)
如果矩阵存储在行主中,则 X、Y 和 X*Y 为:
IF ROW MAJOR: [x1, x2 [y1, y2 = [x1y1+x2y3, x1y2+x2y4;
x3, x4] y3, y4] x3y1+x4y3, x3y2+x4y4];
X*Y in memory if COL major [x1y1+x3y2, x2y1+x4y2, x1y3+x3y4, x2y3+x4y4]
if ROW major [x1y1+x2y3, x1y2+x2y4, x3y1+x4y3, x3y2+x4y4]
Run Code Online (Sandbox Code Playgroud)
这里没有什么深刻的事情。这只是两个不同的约定。这就像以英里或公里为单位进行测量。无论哪种都有效,您不能在不转换的情况下在两者之间来回切换!