【问题标题】:How to pass Blitz++ subarray as an input/output parameter of a procedure如何将 Blitz++ 子数组作为过程的输入/输出参数传递
【发布时间】:2014-10-14 08:29:21
【问题描述】:

我有一个 FFT 过程 fftconvx 将两个张量 TtnsrS 作为输入参数,并将结果生成另一个张量 G。所有张量都定义为 Blitz++ 数组Array<complex<double>, N>,其中N 是数组的秩。必须在双循环内多次调用过程fftconvx

理想情况下,我想传递子数组Stnsr(ri,rj,rk,0)Stnsr(ri,rj,rk,1) 并将结果接收到子数组Gtnsr(t,p,ri,rj,rk,0)Gtnsr(t,p,ri,rj,rk,1) 中,如下所示:

fftconvx( Gtnsr(t,p,ri,rj,rk,0), Ttnsr, Stnsr(ri,rj,rk,0) );

变量ri,rj,rk 是 Blitz++ 数组范围。不幸的是,这不起作用并导致以下编译错误:

error: invalid initialization of non-const reference of type 
‘blitz::Array<std::complex<double>, 3>&’ from an rvalue of type 
‘blitz::SliceInfo<std::complex<double>, int, int, blitz::Range, blitz::Range, 
 blitz::Range, int, blitz::nilArraySection, blitz::nilArraySection, 
 blitz::nilArraySection, blitz::nilArraySection, blitz::nilArraySection>::T_slice
{aka blitz::Array<std::complex<double>, 3>}’

fftconvx(Gtnsr(t,p,ri,rj,rk,0), Ttnsr, Stnsr(ri,rj,rk,0));

fftconvx 的签名是:

void fftconvx(Array<complex<double>, 3> &c,
              Array<complex<double>, 3> x2,
              Array<complex<double>, 3> x1,
              ...);

还有更多的数组和变量作为输入参数传递,但为简洁起见,我省略了它们。

到目前为止,我已经提出了基于临时数组SG的解决方案:

S(ri,rj,rk) = Stnsr(ri,rj,rk,0);

fftconvx(G, Ttnsr, S);

Gtnsr(t,p,ri,rj,rk,0) = G(ri,rj,rk);

我相信有一个更优雅的解决方案。

【问题讨论】:

  • fftconvx 是如何声明的?

标签: c++ multidimensional-array procedure blitz++


【解决方案1】:

在不知道 Blitz++ 的情况下,我提供了这个可能的解决方案。

看起来 Gtnsr 是一个 SliceInfo 而不是一个数组,但它有一个运算符数组。

所以把fftconvx改成

template<class SliceOrArray>
void fftconvx(SliceOrArray &c,
              const Array<complex<double>, 3> x2,
              const Array<complex<double>, 3> x1,
              ...);

如果 fftconvx 中的操作允许使用切片,可能会起作用。

如果 Blitz++ 已更新为 C++11,则以下内容也可能有效。

G fftconvx(   const Array<complex<double>, 3> x2,
              const Array<complex<double>, 3> x1,
              ...) {
    G c;
    ...
    return c; // C++11 NRVO
};

然后调用

Gtnsr(t,p,ri,rj,rk,0) = fftconvx( ... );

【讨论】:

  • 感谢您的建议。第一个选项导致以下错误:error: in passing argument 1 of ‘void ftconvx(SliceOrArray&amp;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;, fftw_plan, fftw_plan, int, int, int, blitz::Range, blitz::Range, blitz::Range) [with SliceOrArray = blitz::Array&lt;std::complex&lt;double&gt;, 3&gt;; fftw_plan = fftw_plan_s*]’.
  • 第二个选项有效。函数应该定义为Array&lt;complex&lt;double&gt;, 3&gt; fftconvx(Array&lt;complex&lt;double&gt;, 3&gt; x2, Array&lt;complex&lt;double&gt;, 3&gt; x1, ...),返回的Blitz++数组应该在fftconvx的末尾定义为Array&lt;complex&lt;double&gt;, 3&gt; c( x3t(ri,rj,rk) / (8.0*mi*mj*mk) ); return c;这也解决了将子数组Stnsr(ri,rj,rk,0)直接传递给fftconvx的问题。
猜你喜欢
  • 2011-02-22
  • 2013-08-22
  • 1970-01-01
  • 2015-12-09
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
相关资源
最近更新 更多