[next] [prev] [prev-tail] [tail] [up]

### 7 Parallel environment routines

#### 7.1 psb_init — Initializes PSBLAS parallel environment

    call psb_init(ctxt, np, basectxt, ids, extcomm)

This subroutine initializes the PSBLAS parallel environment, defining a virtual parallel machine.

Type:

  Synchronous.

On Entry

np

  Number of processes in the PSBLAS virtual parallel machine.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. Default: use all available processes.

basectxt

  the initial PSBLAS communication context. The new context will be defined from the processes participating in the initial one.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. Default: use MPI_COMM_WORLD.

ids

  Identities of the processes to use for the new context; the argument is ignored when np is not specified. This allows the processes in the new environment to be in an order different from the original one.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer array. Default: use the indices (0…np- 1).

extcomm

  an alternative initial MPI communicator. The new context will be defined from the processes participating in the initial one.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. Default: use MPI_COMM_WORLD.

On Return

ctxt

  the communication context identifying the virtual parallel machine, type psb_ctxt_type. Note that this is always a duplicate of basectxt, so that library communications are completely separated from other communication operations.
  Scope: global.
  Type: required.
  Intent: out.
  Specified as: an integer variable.

Notes

1. A call to this routine must precede any other PSBLAS call.

2. It is an error to specify a value for np greater than the number of processes available in the underlying base parallel environment.

#### 7.2 psb_info — Return information about PSBLAS parallel environment

    call psb_info(ctxt, iam, np)

This subroutine returns information about the PSBLAS parallel environment, defining a virtual parallel machine.

Type:

  Asynchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

On Return

iam

  Identifier of current process in the PSBLAS virtual parallel machine.
  Scope: local.
  Type: required.
  Intent: out.
  Specified as: an integer value. -1 ≤ iam ≤ np- 1

np

  Number of processes in the PSBLAS virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: out.
  Specified as: an integer variable.

Notes

1. For processes in the virtual parallel machine the identifier will satisfy 0 ≤ iam ≤ np- 1;

2. If the user has requested on psb_init a number of processes less than the total available in the parallel execution environment, the remaining processes will have on return iam = -1; the only call involving ctxt that any such process may execute is to psb_exit.

#### 7.3 psb_exit — Exit from PSBLAS parallel environment

    call psb_exit(ctxt)
    call psb_exit(ctxt,close)

This subroutine exits from the PSBLAS parallel virtual machine.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

close

  Whether to close all data structures related to the virtual parallel machine, besides those associated with ctxt.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: a logical variable, default value: true.

Notes

1. This routine may be called even if a previous call to psb_info has returned with iam = -1; indeed, it it is the only routine that may be called with argument ctxt in this situation.

2. A call to this routine with close=.true. implies a call to MPI_Finalize, after which no parallel routine may be called.

3. If the user whishes to use multiple communication contexts in the same program, or to enter and exit multiple times into the parallel environment, this routine may be called to selectively close the contexts with close=.false., while on the last call it should be called with close=.true. to shutdown in a clean way the entire parallel environment.

#### 7.4 psb_get_mpi_comm — Get the MPI communicator

    icomm = psb_get_mpi_comm(ctxt)

This function returns the MPI communicator associated with a PSBLAS context

Type:

  Asynchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

On Return

Function value

  The MPI communicator associated with the PSBLAS virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: out.

Notes The subroutine version psb_get_mpicomm is still available but is deprecated.

#### 7.5 psb_get_mpi_rank — Get the MPI rank

    rank = psb_get_mpi_rank(ctxt, id)

This function returns the MPI rank of the PSBLAS process id

Type:

  Asynchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

id

  Identifier of a process in the PSBLAS virtual parallel machine.
  Scope: local.
  Type: required.
  Intent: in.
  Specified as: an integer value. 0 ≤ id ≤ np- 1

On Return

Funciton value

  The MPI rank associated with the PSBLAS process id.
  Scope: local.
  Type: required.
  Intent: out.

Notes The subroutine version psb_get_rank is still available but is deprecated.

#### 7.6 psb_wtime — Wall clock timing

    time = psb_wtime()

This function returns a wall clock timer. The resolution of the timer is dependent on the underlying parallel environment implementation.

Type:

  Asynchronous.

On Exit

Function value

  the elapsed time in seconds.
  Returned as: a real(psb_dpk_) variable.

#### 7.7 psb_barrier — Sinchronization point parallel environment

    call psb_barrier(ctxt)

This subroutine acts as an explicit synchronization point for the PSBLAS parallel virtual machine.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

#### 7.8 psb_abort — Abort a computation

    call psb_abort(ctxt)

This subroutine aborts computation on the parallel virtual machine.

Type:

  Asynchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

#### 7.9 psb_bcast — Broadcast data

    call psb_bcast(ctxt, dat [, root, mode, request])

This subroutine implements a broadcast operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  On the root process, the data to be broadcast.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array, or a character or logical variable, which may be a scalar or rank 1 array. Type, kind, rank and size must agree on all processes.

root

  Root process holding data to be broadcast.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value 0 <= root <= np- 1, default 0

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On all processes other than root, the broadcasted data.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array, or a character or logical scalar. Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_bcast(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_bcast(ctxt,dat,mode=psb_collective_start_,request=bcast_request)
         ....... ! Do not access dat
         call psb_bcast(ctxt,dat,mode=psb_collective_end_, request=bcast_request)

#### 7.10 psb_sum — Global sum

    call psb_sum(ctxt, dat [, root, mode, request])

This subroutine implements a sum reduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global sum.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

root

  Process to hold the final sum, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the sum operation.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array.
  Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_sum(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_sum(ctxt,dat,mode=psb_collective_start_,request=sum_request)
         ....... ! Do not access dat
         call psb_sum(ctxt,dat,mode=psb_collective_end_,request=sum_request)

#### 7.11 psb_max — Global maximum

    call psb_max(ctxt, dat [, root, mode, request])

This subroutine implements a maximum valuereduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global maximum.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: an integer or real variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

root

  Process to hold the final maximum, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the maximum operation.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer or real variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_max(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_max(ctxt,dat,mode=psb_collective_start_,request=max_request)
         ....... ! Do not access dat
         call psb_max(ctxt,dat,mode=psb_collective_end_,request=max_request)

#### 7.12 psb_min — Global minimum

    call psb_min(ctxt, dat [, root, mode, request])

This subroutine implements a minimum value reduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global minimum.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: an integer or real variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

root

  Process to hold the final value, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the minimum operation.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer or real variable, which may be a scalar, or a rank 1 or 2 array.
  Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_min(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_min(ctxt,dat,mode=psb_collective_start_,request=min_request)
         ....... ! Do not access dat
         call psb_min(ctxt,dat,mode=psb_collective_end_,request=min_request)

#### 7.13 psb_amx — Global maximum absolute value

    call psb_amx(ctxt, dat [, root, mode, request])

This subroutine implements a maximum absolute value reduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global maximum.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

root

  Process to hold the final value, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the maximum operation.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_amx(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_amx(ctxt,dat,mode=psb_collective_start_,request=amx_request)
         ....... ! Do not access dat
         call psb_amx(ctxt,dat,mode=psb_collective_end_,request=amx_request)

#### 7.14 psb_amn — Global minimum absolute value

    call psb_amn(ctxt, dat [, root, mode, request])

This subroutine implements a minimum absolute value reduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global minimum.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array. Type, kind, rank and size must agree on all processes.

root

  Process to hold the final value, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the minimum operation.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array.
  Type, kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

2. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_amn(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

3. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_amn(ctxt,dat,mode=psb_collective_start_,request=amn_request)
         ....... ! Do not access dat
         call psb_amn(ctxt,dat,mode=psb_collective_end_,request=amn_request)

#### 7.15 psb_nrm2 — Global 2-norm reduction

    call psb_nrm2(ctxt, dat [, root, mode, request])

This subroutine implements a 2-norm value reduction operation based on the underlying communication library.

Type:

  Synchronous.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The local contribution to the global minimum.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: a real variable, which may be a scalar, or a rank 1 array. Kind, rank and size must agree on all processes.

root

  Process to hold the final value, or -1 to make it available on all processes.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value -1 <= root <= np- 1, default -1.

mode

  Whether the call is started in non-blocking mode and completed later, or is executed synchronously.
  Scope: global.
  Type: optional.
  Intent: in.
  Specified as: an integer value. The action to be taken is determined by its bit fields, which can be set with bitwise OR. Basic action values are psb_collective_start_, psb_collective_end_. Default: both fields are selected (i.e. require synchronous completion).

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

On Return

dat

  On destination process(es), the result of the 2-norm reduction.
  Scope: global.
  Type: required.
  Intent: inout.
  Specified as: a real variable, which may be a scalar, or a rank 1 array.
  Kind, rank and size must agree on all processes.

request

  A request variable to check for operation completion.
  Scope: local.
  Type: optional.
  Intent: inout.
  If mode specifies non-blocking action, then this variable must be present.

Notes

1. This reduction is appropriate to compute the results of multiple (local) NRM2 operations at the same time.

2. Denoting by dati the value of the variable dat on process i, the output res is equivalent to the computation of

   with care taken to avoid unnecessary overflow.

3. The dat argument is both input and output, and its value may be changed even on processes different from the final result destination.

4. The mode argument can be built with the bitwise IOR() operator; in the following example, the argument is forcing immediate completion, hence the request argument needs not be specified:

         call psb_nrm2(ctxt,dat,mode=ior(psb_collective_start_,psb_collective_end_))

5. When splitting the operation in two calls, the dat argument must not be accessed between calls:

         call psb_nrm2(ctxt,dat,mode=psb_collective_start_,request=nrm2_request)
         ....... ! Do not access dat
         call psb_nrm2(ctxt,dat,mode=psb_collective_end_,request=nrm2_request)

#### 7.16 psb_snd — Send data

    call psb_snd(ctxt, dat, dst, m)

This subroutine sends a packet of data to a destination.

Type:

  Synchronous: see usage notes.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

dat

  The data to be sent.
  Scope: local.
  Type: required.
  Intent: in.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array, or a character or logical scalar. Type, kind and rank must agree on sender and receiver process; if m is not specified, size must agree as well.

dst

  Destination process.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer value 0 <= dst <= np- 1.

m

  Number of rows.
  Scope: global.
  Type: Optional.
  Intent: in.
  Specified as: an integer value 0 <= m <= size(dat, 1).
  When dat is a rank 2 array, specifies the number of rows to be sent independently of the leading dimension size(dat, 1); must have the same value on sending and receiving processes.

On Return

Notes

1. This subroutine implies a synchronization, but only between the calling process and the destination process dst.

#### 7.17 psb_rcv — Receive data

    call psb_rcv(ctxt, dat, src, m)

This subroutine receives a packet of data to a destination.

Type:

  Synchronous: see usage notes.

On Entry

ctxt

  the communication context identifying the virtual parallel machine.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer variable.

src

  Source process.
  Scope: global.
  Type: required.
  Intent: in.
  Specified as: an integer value 0 <= src <= np- 1.

m

  Number of rows.
  Scope: global.
  Type: Optional.
  Intent: in.
  Specified as: an integer value 0 <= m <= size(dat, 1).
  When dat is a rank 2 array, specifies the number of rows to be sent independently of the leading dimension size(dat, 1); must have the same value on sending and receiving processes.

On Return

dat

  The data to be received.
  Scope: local.
  Type: required.
  Intent: inout.
  Specified as: an integer, real or complex variable, which may be a scalar, or a rank 1 or 2 array, or a character or logical scalar. Type, kind and rank must agree on sender and receiver process; if m is not specified, size must agree as well.

Notes

1. This subroutine implies a synchronization, but only between the calling process and the source process src.

[next] [prev] [prev-tail] [front] [up]