6.4 库过程 BACKWARD FORWARD


本节所描述的映射查询子程序和计算函数可在HPF库模块HPF_LIBRARY中获得。使用这些过程时,必须与它们所处的每个作用域单元中的适当的USE语句一起使用。它们不是内部函数。

6.4.1 映射查询子程序

HPF提供了一些数据映射指令,这些指令实际上是建议性的。映射查询子程序允许程序在运行时确定一个数组的实际映射。当引用一个外部子程序时,它对于了解确切的映射尤其重要。正是由于这些原因,HPF包含了映射查询子程序,这些子程序描述了数组实际上是怎样被映射到机器上的。为保持很小的例程数目,这些查询过程被构造成具有可选INTENT(OUT)参数的子程序的形式。

6.4.2 位维护函数

HPF库包括三个基本的位维护函数。LEADZ计算一个整数描述中前导零的位数。POPCNT统计整数中1的位数。POPPAR计算一个整数的奇偶性。

6.4.3 数组归约函数

HPF增加了一些新的数组归约函数,这些函数的操作方式与Fortran的SUM和ANY内部函数相同。这些新的归约函数是IALL,IANY,IPARITY和PARITY,它们分别对应于下面的具有交换性,结合性的二进制操作:IAND,IOR,IEOR和.NEQV.。

在这些函数的说明中,使用术语“XXX规约”,在这里,XXX是上面的二进制操作符之一。下面通过一个例子对这些函数进行定义。对于mask的相应元素为真的array中的所有元素,其IAND规约的值是在result中所计算出的标量整数。

 result=IAND_IDENTITY_ELEMENT
 DO i_1=LBOUND(array,1),UBOUND(array,1)
  ...
   DO i_n=LBOUND(array,n),UBOUND(array,n)
    IF(mask(i_1,i_2,...,i_n))&
     result=IAND(result,array(i_1,i_2,...,i_n)
   END DO
  ...
 END DO

在这里,n是array的维数且IAND_IDENTITY_ELEMENT是一个所有位都为1的整数。其它的三个规约也是类似定义的。其中,IOR和IEOR的特性元素是0。而.NEQV.的特性元素是.FALSE.

6.4.4 数组组合分散函数

XXX_SCATTER函数是一些一般化的数组归约函数,在这些函数中,数组元素的任意子集可被组合在一起以产生一个结果元素;对应于结果元素的子集是非重叠的。语言中11个归约操作的每一个都对应于一个分散函数,而且COPY_SCATTER支持用相应子集中的任意一个值来覆盖一个已存在的值。本节中将描述源数组元素与结果元素建立关联的方法;6.7节中的单个函数说明将描述把它们的值组合在一起的方法。

除了下面所提到的特殊情况外,这些函数的一般形式是:

 XXX_SCATTER(ARRAY,BASE,INDX1,...,INDXn,MASK)

XXX所允许的值是ALL,ANY,COPY,COUNT,IALL,IANY,IPARITY,MAXVAL,MINVAL,PARITY,PRODUCT,以及SUM。ARRAY,MASK以及所有的INDX数组都是符合HPF要求的参数。INDX数组是整型的,并且INDX参数的个数必须等于BASE的维数。参数MASK是逻辑型的,而且是可选的。除COUNT_SCATTER之外,ARRAY和BASE都是同种类型的数组。对于COUNT_SCATTER,ARRAY是逻辑型的,BASE是整型的。(对于ALL_SCATTER,ANY_SCATTER,COUNT_SCATTER,和PARITY_SCATTER,参数ARRAY必须是逻辑型的。这些函数不具有可选的MASK参数。为符合Fortran标准的惯例,这些函数所要求的ARRAY参数在6.7节的说明中被称为MASK。)在所有这些情况下,结果数组都是一个与BASE具有相同类型,种类参数,以及形状的数组。

因为所有的INDX数组都与ARRAY具有相同的形状,因此对于ARRAY中的每一个元素a,在每个INDX数组中都有一个元素与之相对应。对于每一个j=1,2,..,n,在这里n是BASE的维数,令sj是对应于ARRAY中元素a的INDXj的元素值。这些索引值决定了受ARRAY元素a影响的结果元素。对于每个索引sj,BASE中的相应索引是bj=sj+LBOUND(BASE,j)-1。

整数bj,j=1,...n,组成了选择BASE中元素的下标:BASE(b1,b2,...,bn)。因为BASE和结果是相符的,因此对于BASE中的每个元素都有一个结果元素与之相对应。

这样INDX数组就建立了一个从ARRAY的所有元素到结果和BASE给定元素之间的映射。从另一个方向考虑,此映射在ARRAY的元素集合S与BASE的每个元素之间建立了联系。

如果S是空的,则与BASE中元素b相对应的结果元素具有相同的值b。

如果S是非空的,则S的元素将与元素b组合在一起以产生结果元素。分散函数的详细说明描述了组合这些值的专门方式。例如,对于SUM_SCATTER,如果S的元素是a1,...,am,则对应于BASE中元素b的结果元素是SUM(/a1,a2,...,am,b/)的值。

注意,INDX数组的元素必须是非负的,且INDXj不能超过SIZE(BASE,j)。计算结果不受所定义的BASE索引上下界的影响;它仅依赖于BASE的形状。

注意,由于标量与任何数组都是相符的,因此可用标量来代替INDX数组,在这种情况下结果的一个超面被选定。见下面的例子。

如果可选的,最后一个MASK参数也存在,则ARRAY中参加操作的仅是那些MASK的对应元素为真的元素。ARRAY和INDX数组中的所有其它元素被忽略且对于结果的任何元素没有任何影响。

例如,如果

 A是数组 ;      B是数组; 

 I1是数组 ;      I2是数组

  SUM_SCATTER(A,B,I1,I2)的结果是
  SUM_SCATTER(A,B,2,I2)的结果是
  SUM_SCATTER(A,B,I1,2)的结果是
  SUM_SCATTER(A,B,2,2)的结果是
如果A是数组,B是数组,且C是数组,则SUM_SCATTER(A,B,IND,MASK(A .GT. 0))的结果是

6.4.5 数组前缀和后缀函数

当扫描(scan)一个向量时,每个结果元素都是它前面(对于前缀扫描)或它后面(对于后缀扫描)的向量元素的函数。这些函数提供了对数组的和子数组扫描操作。除了下面所提到的特殊情况外,这些函数的一般形式是:

  XXX_PREFIX(ARRAY,DIM,MASK,SEGMENT,EXCLUSIVE)
  XXX_SUFFIX(ARRAY,DIM,MASK,SEGMENT,EXCLUSIVE)

XXX的允许值是ALL,ANY,COPY,COUNT,IALL,IPARITY,MAXVAL,MINVAL,PARITY,PRODUCT和SUM。

当下面的注释既适用于前缀又适用于后缀的例程形式时,我们称它们为YYYFIX函数。

参数DIM,MASK,SEGMENT和EXCLUSIVE是可选的。COPY_YYYFIX函数没有MASK或EXCLUSIVE参数。ALL_YYYFIX,ANY_YYYFIX,COUNT_YYYFIX和PARITY_YYYFIX函数没有MASK参数。它们的ARRAY参数必须是逻辑型的;在6.7节的说明中它被指示为MASK。

参数MASK和SEGMENT必须是逻辑型的。SEGMENT必须与ARRAY具有相同的形状。MASK必须与ARRAY相符。EXCLUSIVE是一个逻辑型标量。DIM是一个介于1和ARRAY的维数之间的整数。

结果值:结果与ARRAY具有相同的形状,且,除COUNT_YYYFIX外,与ARRAY具有相同的类型和种类参数。(COUNT_YYYFIX的结果是缺省整数)

在每种情况下,结果的每一个元素都是由ARRAY的某些给定元素的值所决定的,决定的方式是其专门函数所特有的,在下面的函数说明中我们将对其进行描述。可选参数影响了对应于每个结果元素的ARRAY中元素的选择;ARRAY中选定的元素将作用于结果元素。本节充分描述了ARRAY的哪些元素作用于给定的结果元素。

如果对应于结果的给定元素,没有在ARRAY中选定元素,则该结果元素被置成一个缺省值,该值是其专门函数所特有的,在下面的函数说明中我们将对其进行描述。

对于任何一个给定的结果元素r,令a是ARRAY中对应的元素。除非不满足下列规则之一,否则ARRAY中的每个元素都将作用于r。

1.如果函数是XXX_PREFIX,则ARRAY的元素序列中在a之后的所有元素都不会作用于r。如果函数是XXX_SUFFIX,则ARRAY的元素序列中在a之前的所有元素都不会作用于r。

2.如果提供了DIM参数,则ARRAY中元素z要想作用于r,只有其除DIM维之外的所有索引与a中的相应索引都相同。(如果省略DIM参数,则ARRAY,MASK和SEGMENT按照数组元素的次序被处理,就好象把它们临时当作了一维数组。如果存在DIM参数,则沿着ARRAY的选定维执行一组完全独立的扫描操作。)

3.如果提供了MASK参数,则仅当对应于z的MASK中的元素为真时,ARRAY的元素z才会作用于r。(对于MASK中为假的元素,与其相对应的数组元素不会对结果产生任何影响。但是,结果在所有的位置仍然有定义,即使对应于该位置的MASK为假。)

4.如果提供了SEGMENT参数,则ARRAY的元素z不会影响r的条件是存在ARRAY的一些中间元素w(可能包括z本身),它们具有下面的所有特性:

(a)如果函数是XXX_PREFIX,则w在数组的元素序列中,不位于z之前,但位于a之前;如果函数是XXX_SUFFIX,则w在数组的元素序列中,不位于z之后,但位于a之后。

(b)如果存在DIM参数,w的除DIM维之外的所有索引与a中的相应索引都相同;且

(c)SEGMENT中对应于w的元素值与SEGMENT中对应于a的值不同。(另一方面,当从z延伸到a时,仅当存在SEGMENT值的一个完整串,z就可以起作用。)

5.如果提供了EXCLUSIVE参数,且其值为真,则a本身不会影响r。

这些一般的规则导致下列重要的情形:

情形(i): 如果ARRAY是一维的,则XXX_PREFIX(ARRAY)的结果元素i由ARRAY的第一个元素所决定;XXX_SUFFIX(ARRAY)的结果元素SIZE(ARRAY)-i+1由ARRAY的最后一个元素所决定。

情形(ii): 如果ARRAY的维数超过一维,则XXX_PREFIX(ARRAY)的每一个结果元素的值由ARRAY中的对应元素a和ARRAY的数组元素序列中位于a之前的所有元素所决定。对于XXX_SUFFIX,a由ARRAY的数组元素序列中对应于a或紧随a的元素所决定。

情形(iii):XXX_PREFIX(ARRAY,MASK=MASK)的每个结果元素由ARRAY中指定的元素所决定,即ARRAY中的对应元素a和ARRAY的数组元素序列中a之前的所有元素所决定,但是仅当MASK的对应元素为真时,ARRAY中的一个元素才能对结果起作用。如果这一约束导致没有选到任何数组元素来作用于一些结果元素,则结果的那个元素被给定函数置成缺省值。

情形(iv): XXX_PREFIX(ARRAY,DIM=DIM)的每个结果元素由ARRAY中指定的元素所决定,即由ARRAY中的对应元素a和ARRAY中沿DIM维位于a之前的所有元素所决定;例如,在SUM_PREFIX(A(1:N,1:N),DIM=2)中,结果元素(i1,i2)可被计算为SUM(A(i1,1:i2))。更一般地,在SUM_PREFIX(ARRAY,DIM)中,结果元素i1,i2,...iDIM,...in可被计算为SUM(ARRAY(i1,i2,...,:iDIM,...,in))。(注意最后那个表达式中iDIM前的冒号。)

情形(v): 如果ARRAY是一维的,则XXX_PREFIX(ARRAY,EXCLUSIVE=.TRUE.)的结果元素i由ARRAY的头i-1个元素所决定。

情形(vi): 可选参数可用于任何组合中。

对用户的建议:每个过渡点上的新段都是以false开始,以true结束或以true开始,以false结束;这样,这
样任何一个段都可用一个最大的逻辑值连续序列来指示:

(/T,T,T,F,T,F,F,F,T,F,F,T/)
-------------------------- 七段

(对用户的建议结束)

基本原理:

一种现存的库是通过指示每一段的起始点来为各段定界。而另一种则是通过指示每一段的结束点来为各段定界。每一种方法都各有其优点。还有一个问题是当执行一个后缀而非前缀时,这一习惯是否应该改变。HPF采纳了上面的对称描述。这一描述的主要优点是:

(A)因为同一段指示符无须改变其解释就可用于前缀和后缀(开始和结束是相对的),因此它是对称的。

(B)通过使用PREITY_PREFIX或PARITY_SUFFIX可以很容易地将开始位或结束位描述转换为这种形式。这些是编译器所承认的标准风格:

  SUM_PREFIX(FOO,SEGMENT=PARITY_PREFIX(START_BITS))
  SUM_PREFIX(FOO,SEGMENT=PARITY_SUFFIX(STOP_BITS))
  SUM_PREFIX(FOO,SEGMENT=PARITY_SUFFIX(START_BITS))
  SUM_PREFIX(FOO,SEGMENT=PARITY_PREFIX(STOP_BITS))

(基本原理结束)

例子:下面的这些例子阐述了SUM_PREFIX可选参数的所有可能组合。SUM_YYYFIX的缺省值是0。

情形(i): SUM_PREFIX((/1,3,5,7/))的结果是

情形(ii): 如果B是数组, 则SUM_PREFIX(B)的结果是数组
情形(iii):如果A是数组, 则SUM_PREFIX(A,MASK=A.LT.6|的结果是

情形(iv): 如果B是数组,则SUM_PREFIX(B,DIM=1)的结果是数组且SUM_PREFIX(B,DIM=2)的结果是数组
情形(v): SUM_PREFIX((/1,3,5,7/),EXCLUSIVE=.TRUE.)的结果是

情形(vi): 如果B是数组,M是数组,且S是数组,则: 

  SUM_PREFIX(B,DIM=2,MASK=M,SEGMENT=S,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,DIM=2,MASK=M,SEGMENT=S,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,DIM=2,MASK=M,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,DIM=2,MASK=M,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,DIM=2,SEGMENT=S,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,DIM=2,SEGMENT=S,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,DIM=2,EXCLUSIVE=.TRUE.)的结果是。  

  SUM_PREFIX(B,DIM=2,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,MASK=M,SEGMENT=S,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,MASK=M,SEGMENT=S,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,MASK=M,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,MASK=M,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,SEGMENT=S,EXCLUSIVE=.TRUE.)的结果是
  SUM_PREFIX(B,SEGMENT=S,EXCLUSIVE=.FALSE.)的结果是
  SUM_PREFIX(B,EXCLUSIVE=.TRUE.)的结果是

  SUM_PREFIX(B,EXCLUSIVE=.TRUE.)的结果是
                   

6.4.6 数组排序函数

HPF中包含了用于对多维数组进行排序的过程。SORT_UP和SORT_DOWN函数返回排序过的数组;GRADE_UP和GRADE_DOWN函数返回排序过的置换。可沿某一给定的维对数组进行排序,也可按数组元素的顺序把整个数组看成是一个序列。等级函数使用固定排序,并考虑了用主次关键字来对结构进行方便地排序。


Copyright: NPACT BACKWARD FORWARD