Chapel 中的用户定义函数具有奇怪的行为 .type 与 .eltType
User defined function in Chapel has odd behavior .type vs .eltType
我想写一个连接函数,所以我想出了
proc concat(x:[], y:[]) {
const d:int = x.size + y.size;
var v:[1..d] x.type;
writeln("\n d: ", d);
writeln("\n x.domain: ", x.domain);
writeln("\n y.domain: ", y.domain);
var k = 1;
for i in x.domain {
v[k] = x[i];
writeln("i: ", i, " k: ", k, " x[i]: ", x[i], " v[k]: ", v[k]);
k += 1;
}
for i in y.domain {
v[k] = y[i];
writeln("i: ", i, " k: ", k, " y[i]: ", y[i], " v[k]: ", v[k]);
k += 1;
}
writeln("\n v: ", v);
return v;
}
但它的输出非常奇怪
var x: [1..3] real = [1.1, 2.2, 3.3],
y: [9..11] real = [9.9, 10.10, 11.11];
var z = concat(x,y);
writeln(z);
生产
d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1 k: 1 x[i]: 1.1 v[k]: 1.1 1.1 1.1
i: 2 k: 2 x[i]: 2.2 v[k]: 2.2 2.2 2.2
i: 3 k: 3 x[i]: 3.3 v[k]: 3.3 3.3 3.3
i: 9 k: 4 y[i]: 9.9 v[k]: 9.9 9.9 9.9
i: 10 k: 5 y[i]: 10.1 v[k]: 10.1 10.1 10.1
i: 11 k: 6 y[i]: 11.11 v[k]: 11.11 11.11 11.11
v: 1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
这有点令人费解。
看起来您的代码混淆了 .type
和 .eltType
。给定一个数组变量,如 var A: [1..3] real;
,A.type
实际上是 [1..3] real
,而 A.eltType
只是 real
。所以当你声明时:
var v:[1..d] x.type;
而不是获取您想要的 real
值的数组,您实际上是在声明一个数组,其元素本身就是 real
值的数组。
然后,由于 Chapel 支持从标量到数组的提升赋值(例如,A = 0.0
将是将上面的 A
数组清零的简单方法),当您复制元素时从您的原始数组到 v
,v
的每个数组元素都将值存储在其每个位置,导致值的三倍。
将 v
的声明更改为:
var v:[1..d] x.eltType;
应该给你你想要的。 Here's the corrected version online.
var x: [1.. 3] real = [1.1, 2.2, 3.3],
y: [9..11] real = [9.9, 10.10, 11.11];
var z = concat( x, y );
writeln( z );
proc concat( x:[], y:[] ) {
const d:int = x.size + y.size;
// var v:[1..d] x.type; // ------------------------------------ FAIL
/* d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1, k: 1, x[i]: 1.10, v[k]: 1.1 1.1 1.1
i: 2, k: 2, x[i]: 2.20, v[k]: 2.2 2.2 2.2
i: 3, k: 3, x[i]: 3.30, v[k]: 3.3 3.3 3.3
i: 9, k: 4, y[i]: 9.90, v[k]: 9.9 9.9 9.9
i: 10, k: 5, y[i]: 10.10, v[k]: 10.1 10.1 10.1
i: 11, k: 6, y[i]: 11.11, v[k]: 11.11 11.11 11.11
v:
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
*/
var v:[1..d] x.eltType; // ------------------------------------ PASS
/* d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1, k: 1, x[i]: 1.10, v[k]: 1.1
i: 2, k: 2, x[i]: 2.20, v[k]: 2.2
i: 3, k: 3, x[i]: 3.30, v[k]: 3.3
i: 9, k: 4, y[i]: 9.90, v[k]: 9.9
i: 10, k: 5, y[i]: 10.10, v[k]: 10.1
i: 11, k: 6, y[i]: 11.11, v[k]: 11.11
v:
1.1 2.2 3.3 9.9 10.1 11.11
1.1 2.2 3.3 9.9 10.1 11.11
*/
writeln( "\n d: ", d );
writeln( "x.domain: ", x.domain );
writeln( "y.domain: ", y.domain );
var k = 1;
for i in x.domain {
v[k] = x[i];
// writeln("i: ", i, " k: ", k, " x[i]: ", x[i], " v[k]: ", v[k]);
writef( "i: %{###},", i ); writef( " k: %{###},", k ); writef( " x[i]: %{####.##},", x[i] ); writeln( " v[k]: ", v[k] );
k += 1;
}
for i in y.domain {
v[k] = y[i];
// writeln("i: ", i, " k: ", k, " y[i]: ", y[i], " v[k]: ", v[k]);
writef( "i: %{###},", i ); writef( " k: %{###},", k ); writef( " y[i]: %{####.##},", y[i] ); writeln( " v[k]: ", v[k] );
k += 1;
}
writeln( "\nv:\n", v );
return v;
}
( and both alternatives, side by side, left for any further experimentations )
我想写一个连接函数,所以我想出了
proc concat(x:[], y:[]) {
const d:int = x.size + y.size;
var v:[1..d] x.type;
writeln("\n d: ", d);
writeln("\n x.domain: ", x.domain);
writeln("\n y.domain: ", y.domain);
var k = 1;
for i in x.domain {
v[k] = x[i];
writeln("i: ", i, " k: ", k, " x[i]: ", x[i], " v[k]: ", v[k]);
k += 1;
}
for i in y.domain {
v[k] = y[i];
writeln("i: ", i, " k: ", k, " y[i]: ", y[i], " v[k]: ", v[k]);
k += 1;
}
writeln("\n v: ", v);
return v;
}
但它的输出非常奇怪
var x: [1..3] real = [1.1, 2.2, 3.3],
y: [9..11] real = [9.9, 10.10, 11.11];
var z = concat(x,y);
writeln(z);
生产
d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1 k: 1 x[i]: 1.1 v[k]: 1.1 1.1 1.1
i: 2 k: 2 x[i]: 2.2 v[k]: 2.2 2.2 2.2
i: 3 k: 3 x[i]: 3.3 v[k]: 3.3 3.3 3.3
i: 9 k: 4 y[i]: 9.9 v[k]: 9.9 9.9 9.9
i: 10 k: 5 y[i]: 10.1 v[k]: 10.1 10.1 10.1
i: 11 k: 6 y[i]: 11.11 v[k]: 11.11 11.11 11.11
v: 1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
这有点令人费解。
看起来您的代码混淆了 .type
和 .eltType
。给定一个数组变量,如 var A: [1..3] real;
,A.type
实际上是 [1..3] real
,而 A.eltType
只是 real
。所以当你声明时:
var v:[1..d] x.type;
而不是获取您想要的 real
值的数组,您实际上是在声明一个数组,其元素本身就是 real
值的数组。
然后,由于 Chapel 支持从标量到数组的提升赋值(例如,A = 0.0
将是将上面的 A
数组清零的简单方法),当您复制元素时从您的原始数组到 v
,v
的每个数组元素都将值存储在其每个位置,导致值的三倍。
将 v
的声明更改为:
var v:[1..d] x.eltType;
应该给你你想要的。 Here's the corrected version online.
var x: [1.. 3] real = [1.1, 2.2, 3.3],
y: [9..11] real = [9.9, 10.10, 11.11];
var z = concat( x, y );
writeln( z );
proc concat( x:[], y:[] ) {
const d:int = x.size + y.size;
// var v:[1..d] x.type; // ------------------------------------ FAIL
/* d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1, k: 1, x[i]: 1.10, v[k]: 1.1 1.1 1.1
i: 2, k: 2, x[i]: 2.20, v[k]: 2.2 2.2 2.2
i: 3, k: 3, x[i]: 3.30, v[k]: 3.3 3.3 3.3
i: 9, k: 4, y[i]: 9.90, v[k]: 9.9 9.9 9.9
i: 10, k: 5, y[i]: 10.10, v[k]: 10.1 10.1 10.1
i: 11, k: 6, y[i]: 11.11, v[k]: 11.11 11.11 11.11
v:
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
1.1 1.1 1.1 2.2 2.2 2.2 3.3 3.3 3.3 9.9 9.9 9.9 10.1 10.1 10.1 11.11 11.11 11.11
*/
var v:[1..d] x.eltType; // ------------------------------------ PASS
/* d: 6
x.domain: {1..3}
y.domain: {9..11}
i: 1, k: 1, x[i]: 1.10, v[k]: 1.1
i: 2, k: 2, x[i]: 2.20, v[k]: 2.2
i: 3, k: 3, x[i]: 3.30, v[k]: 3.3
i: 9, k: 4, y[i]: 9.90, v[k]: 9.9
i: 10, k: 5, y[i]: 10.10, v[k]: 10.1
i: 11, k: 6, y[i]: 11.11, v[k]: 11.11
v:
1.1 2.2 3.3 9.9 10.1 11.11
1.1 2.2 3.3 9.9 10.1 11.11
*/
writeln( "\n d: ", d );
writeln( "x.domain: ", x.domain );
writeln( "y.domain: ", y.domain );
var k = 1;
for i in x.domain {
v[k] = x[i];
// writeln("i: ", i, " k: ", k, " x[i]: ", x[i], " v[k]: ", v[k]);
writef( "i: %{###},", i ); writef( " k: %{###},", k ); writef( " x[i]: %{####.##},", x[i] ); writeln( " v[k]: ", v[k] );
k += 1;
}
for i in y.domain {
v[k] = y[i];
// writeln("i: ", i, " k: ", k, " y[i]: ", y[i], " v[k]: ", v[k]);
writef( "i: %{###},", i ); writef( " k: %{###},", k ); writef( " y[i]: %{####.##},", y[i] ); writeln( " v[k]: ", v[k] );
k += 1;
}
writeln( "\nv:\n", v );
return v;
}
( and both alternatives, side by side, left for any further experimentations )