[英]Is there an O(1) way to separate real and imaginary parts of complex array when passed to pgplot?
我的代码中有一个复杂的float数组,库为我生成了一个数组。 考虑它是这样的:
float _Complex data[N];
为了将其作为具有实部和虚部的单独数组,我遍历该数组并采用以下值:
float real[N];
float imag[N];
for (int pt=0;pt<N;pt++) {
real[pt] = creal(data[pt]);
imag[pt] = cimag(data[pt]));
}
但是,这实际上是低效的,因为这从执行时间和空间上来说都是O(N)
操作。 我想知道是否可以使用某些指针算术来分隔数组,从而减少执行时间和内存使用?
我需要分别绘制实数值和虚数值。 我的绘图库PGPLOT需要将值数组发送给它,因此我不能“就地”使用复杂的数组。
pgplot
库提供了一个无边距的界面来绘制标记数组:
void cpgpt(int n, const float *xpts, const float *ypts, int symbol);
但这只是对cpgpt1
各个调用的一个简单包装。 因此,添加跨步接口很容易:
void cpgpts(int n, int stride, const float *xpts, const float *ypts, int symbol) {
for (int i = 0; i < n; ++i) {
cpgpt1(*xpts, *ypts, symbol);
xpts += stride;
ypts += stride;
}
}
当然,您将需要编写复杂的浮标转换的包装程序。 例如:
void cpgptsc(int n, const float _Complex *pts, int symbol) {
cpgpts(n, 2, (const float*)pts, ((const float*)pts)+1, symbol);
}
例:
// Plot the data as symbols on the Re-Im plane
cpgptsc(count, data, symbol);
您可以类似地重新实现cpgline
:
void cpglines(int n, int stride, const float *xpts, const float *ypts, int symbol) {
cpgmove(*xpts, *ypts);
for (int i = 1; i < n; ++ i) {
xpts += stride;
ypts += stride;
cpgdraw(*xpts, *ypts);
}
}
void cpglinesc(int n, const float _Complex *pts, int symbol) {
cpglines(n, 2, (const float*)pts, ((const float*)pts)+1, symbol);
}
例:
// Plot the data as lines on the Re-Im plane
cpglinesc(count, data);
如果只绘制单个分量(实部或虚部),则为其创建合理的包装器也很简单:
void cpglinesx(int n, int stride, float dx, float x0, const float *ypts) {
cpgmove(x0, *ypts);
for (int i = 1; i < n; ++ i) {
x0 += dx;
ypts += stride;
cpgdraw(x0, *ypts);
}
}
void cpglinesxre(int n, float dx, float x0, const float _Complex *pts) {
cpglinesx(n, 2, dx, x0, (const float*)pts);
}
void cpglinesxim(int n, float dx, float x0, const float _Complex *pts) {
cpglinesx(n, 2, dx, x0, ((const float*)pts)+1);
}
然后,要绘制以x = 0开头,增量为1.0的虚数分量,您需要执行以下操作:
// Plot the imaginary coordinates of all the data
cpglinesxim(count, 1.0, 0.0, data);
鉴于:
float _Complex data[N];
我们知道:
float *ptr = (float *) data;
ptr[2 * n + 0] <- real part.
ptr[2 * n + 1] <- imaginary part.
我们可以在这里看到一些合理化。 基本上, float _Complex
具有与float[2]
相同的内存布局。
修改此值以使所有实数都是连续的,将需要与问题中提到的O(n)
版本相似的操作。
如果您有一个长度为N的输入数组,那么实际上就没有O(1)算法来处理所有输入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.