矢量操作符
如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。
算术操作符
算术操作符(加(+)、减(–)、乘(*)和除(/)),可以作用于内置整数、浮点标量和矢量数据类型。取余操作符(%)只能用于内置整数标量和矢量数据类型。可能有以下情况:
1)两个操作数都是标量。在这种情况下,操作遵循C99规则。
2)一个操作数是标量,另一个是矢量。可以根据常规算术转换将这个标量操作数转换为矢量操作数使用的元素类型,然后宽化为一个矢量,这个新矢量与矢量操作数的元素个数相同。将逐分量地应用操作,得到一个相同大小的矢量。
3)两个操作数是相同类型的矢量。在这种情况下,会逐分量地应用操作,得到相同大小的矢量。
对于整数类型,除以0或者可能得到越界值的除法不会导致异常,而只是得到一个未定义值。对于浮点类型,根据IEEE 754标准的规定,除以0会得到±∞或NaN。
可以通过几个例子来说明一个操作数是标量而另一个操作数是矢量时,算术操作符如何工作,或者两个操作数都是矢量时,算术操作符如何工作。
图4-3中的第一个例子显示了将两个矢量相加:
int4 v_iA = (int4)(7, -3, -2, 5);
int4 v_iB = (int4)(1, 2, 3, 4);
int4 v_iC = v_iA + v_iB;
相加的结果存储在矢量v_iC
中:(8, -1, 1, 9)。
图4-4中的例子显示了一个乘法运算,这里操作数分别为一个矢量和一个标量。在这个例子中,只是将标量按矢量的大小宽化,再将各矢量的分量相乘:
float4 vf = (float4)(3.0f, -1.0f, 1.0f, -2.0f);
float4 result = vf * 2.5f;
存储在矢量result中的乘法结果是(7.5f, -2.5f, 2.5f, -5.0f)
图4-5中的例子显示了可以将一个矢量和一个标量相乘,这里标量会隐式地转换和宽化:
float4 vf = (float4)(3.0f, -1.0f, 1.0f, -2.0f);
float4 result = vf * 2;
存储在矢量result中乘法结果是(6.0f, -2.0f, 2.0f, -4.0f)
关系和相等操作符
关系操作符(大于(>)、小于(<)、大于或等于(>=)和小于或等于(<= )),以及相等操作符(等于(==)和不等于(!=)),可以作用于内置整数、浮点标量和矢量数据类型。结果是一个整数标量或矢量类型。
可能有以下情况:
1)两个操作数都是标量。在这种情况下,操作遵循C99规则。
2)一个操作数是标量,另一个操作数是矢量。可以根据常规算术转换将标量操作数转换为矢量操作数使用的元素类型,然后宽化为一个矢量,这个新矢量与矢量操作数的元素个数相同。逐分量地应用操作,得到相同大小的矢量。
3)两个操作数是相同类型的矢量。在这种情况下,逐分量地应用操作,得到相同大小的矢量。
如果两个源操作数都是标量,结果就是一个类型为int
的有符号整型标量;如果操作数是矢量,则结果是与矢量源操作数大小相同的、有符号的整数类型矢量;如果源操作数是charn
,或ucharn
,则结果类型为charn
;如果源操作数为 shortn
、ushortn
或halfn
,则结果类型为shortn
;如果源操作数为intn
、uintn
或floatn
,结果类型就是intn
;如果源操作数为longn
、ulongn
或doublen
,则结果类型为longn
。
对于标量类型,如果指定的关系为假,则这些操作符返回0
;如果指定关系为真,则返回1
。对于矢量类型,如果指定关系为假,则这些操作符返回0
;如果指定的关系为真,则操作符返回-1
(即,所有位均设置为1
)。如果某一个或两个参数不是一个数(NaN
),则关系操作符总返回0
。如果某一个或两个参数不是一个数(NaN
),相等操作符“等于”(==
)总返回0
。如果某一个或两个参数不是一个数(NaN
)时,“不等于”操作符(! =
)返回1
(对于标量源操作数)或-1
(对于矢量源操作数)。
位操作符
位操作符(位与(&)、位或((|)、异或(^)和非(~)),可以作用于内置整数标量和矢量数据类型。结果是一个整数标量或矢量类型。可能有以下情况:
1)两个操作数都是标量。在这种情况下,操作遵循C99规则。
2)一个操作数是标量,另一个是矢量。可以根据常规算术转换将这个标量操作数转换为矢量操作数使用的元素类型,然后宽化为一个矢量,这个新矢量与矢量操作数的元素个数相同。逐分量地应用操作,得到一个相同大小的矢量。
3)两个操作数是相同类型的矢量。在这种情况下,逐分量地应用操作,得到相同大小的矢量。
逻辑操作符
逻辑操作符(与(&&
)或(I
)),可以作用于内置整数标量和矢量数据类型。结果是一个整数标量或矢量类型。可能有以下情况:
1)两个操作数都是标量。在这种情况下,操作遵循C99规则。
2)一个操作数是标量,另一个是矢量。可以根据常规算术转换将这个标量操作数转换为矢量操作数使用的元素类型,然后宽化为一个矢量,这个新矢量与矢量操作数的元素个数相同。逐分量地应用操作,得到一个相同大小的矢量。
3)两个操作数是相同类型的矢量。在这种情况下,逐分量地应用操作,得到相同大小的矢量。
如果两个源操作数都是标量,逻辑操作符“与”(&&
)只有在左操作数不等于О的情况下才会计算右操作数,逻辑操作符“或”(||)仅当左操作符等于0
的情况下才会计算右操作数。如果其中一个或两个源操作数为矢量类型,那么两个操作数都会计算。
如果两个源操作数都是标量,结果是一个int
类型的有符号整数标量;如果源操作数是矢量,结果是有相同大小的有符号整数类型矢量。如果源操作数是charn
或ucharn
,结果类型为charn
;如果源操作数为 shortn
或ushortn
,则结果类型为shortn
;如果源操作数为intn
或uintn
,结果类型就是intn
;如果源操作数为longn
或ulongn
,则结果类型为longn
。
对于标量类型,如果指定的关系为假,这些操作符会返回0
;如果指定关系为真,则返回1
。对于矢量类型,如果指定关系为假,则这些操作符会返回0
;如果指定的关系为真,则操作符返回-1
(即,所有位均设置为1
)。
逻辑排除操作符(^^
)保留,以备将来使用。
条件操作符
算术一元操作符(+和-)作用于内置标量和矢量数据类型。
算术后自增和前自增(++
)以及后自减和前自减(--
)操作符作用于内置标量和矢量数据类型(但不包括内置浮点标量和矢量数据类型)。这些操作符会对其操作数逐分量地进行处理,最后得到与所处理操作数相同的类型。
逻辑一元操作符“非”(!
)作用于内置标量和矢量数据类型(但不包括内置浮点标量和矢量数据类型)。这些会对其操作数逐分量地进行处理。如果源操作数是标量,则结果是一个int
类型的有符号整数标量;如果源操作数是矢量,则得到相同大小的有符号整数类型矢量;如果源操作数是charn
或ucharn
,结果类型为charn
;如果源操作数为shortn
或ush-ortn
,则结果类型为shortn
;如果源操作数为intn
或uintn
,结果类型就是intn
;如果源操作数为longn
或ulongn
,则结果类型为longn
。
对于标量类型,如果指定的关系为假,则这些操作符会返回0
;如果指定关系为真,则返回1
。对于矢量类型,如果指定关系为假,则这些操作符会返回0;如果指定的关系为真,则操作符返回-1
(即,所有位均设置为1
)。
逗号操作符(,
)作用于表达式,返回一个逗号分隔的表达式列表中最右表达式的类型和值。所有表达式都会从左到右按顺序计算。例如:
//comma acts as a separator not an operator
int a = 1, b = 2, c = 3, x;
//comma acts as an operator
x = a += 2, a + b; //a=3,x=5
x = (a, b, c); //x=3
sizeof
操作符会得到其操作数的大小(字节数)。结果是一个整数值。如果操作数的类型为char
或uchar
,则结果为1
;如果操作数类型为short
、ushort
或half
,则结果为2
;如果操作数类型为int
、uint
或float
,则结果为4
;如果操作数类型为long
、ulong
或double
,则结果为8
;如果操作数是一个矢量类型(包含3个分量的矢量除外),则结果是(矢量中分量个数)*(各标量分量的大小)
,对于包含3个分量的矢量,结果则是4*(各标量分量的大小)
;如果操作数是一个数组类型,则结果是该数组中的总字节数;如果操作数是一个结构或联合类型,则结果就是这个对象中的总字节数,包括内部或尾部填充的字节。
对image2d_t
、image3d_t
、sampler_t
和event_t
类型应用sizeof
操作符的行为由具体实现定义。对于某些实现,sizeof(sampler_t) = 4
,而在有些实现中,这个操作可能会导致一个编译时错误。为了保证跨OpenCL实现的可移植性,建议不要对这些类型使用sizeof
操作符。
一元操作符(*
)指示间接性。如果操作数指示一个对象,则结果是一个指示该对象的左值;如果操作数类型为“指向某个类型type的指针”,那么结果类型就是type
。如果将一个非法值赋给该指针,则间接操作符的行为未定义。
一元操作符(&
)返回其操作数的地址。
赋值操作符
为变量名赋值的操作由赋值操作符(=
)完成,如:
lvalue = expression
赋值操作符将expression
的值存储在lvalue
中。
可能出现以下情况:
1)两个操作数都是标量。在这种情况下,操作遵循C99规则。
2)一个操作数是标量,另一个是矢量。这个标量操作数显式转换为矢量操作数使用的元素类型,然后宽化为一个矢量,这个新矢量与矢量操作数的元素个数相同。逐分量地应用操作,得到一个相同大小的矢量。
3)两个操作数是相同类型的矢量。在这种情况下,逐分量地应用操作,得到相同大小的矢量。
以下表达式是等价的:
lvalue op = expression
lvalue = lvalue op expression
lvalue
和 expression
必须同时满足op和赋值操作符(=
)的要求。