[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS RTL General Purpose (OTS$) Manual


Previous Contents Index

This PL/I example translates a hexadecimal value in ASCII into a fixed binary value. This program continues to prompt for input values until the user presses Ctrl/Z.

One sample of the output generated by this program is as follows:


$ RUN HEX
Hex value:  1A
1A      Hex equals       26 Decimal

Hex value:  C
C       Hex equals       12 Decimal

Hex value:  Ctrl/Z

OTS$DIVCx

The Complex Division routines return a complex result of a division on complex numbers.

Format

OTS$DIVC complex-dividend ,complex-divisor

OTS$DIVCD_R3 complex-dividend ,complex-divisor (VAX only)

OTS$DIVCG_R3 complex-dividend ,complex-divisor

OTS$DIVCS complex-dividend ,complex-divisor

OTS$DIVCT_R3 complex-dividend ,complex-divisor

Each of these formats corresponds to one of the floating-point complex types.


RETURNS


OpenVMS usage: complex_number
type: F_floating complex, D_floating complex, G_floating complex, IEEE S_floating complex, IEEE T_floating complex,
access: write only
mechanism: by value

Complex result of complex division. OTS$DIVC returns an F-floating complex number. OTS$DIVCD_R3 returns a D-floating complex number. OTS$DIVCG_R3 returns a G-floating complex number. OST$DIVCS returns an IEEE S-floating complex number. OTS$DIVCT_R3 returns an IEEE T-floating complex number.


Arguments

complex-dividend


OpenVMS usage: complex_number
type: F_floating complex, D_floating complex, G_floating complex, IEEE S_floating complex, IEEE T_floating complex
access: read only
mechanism: by value

Complex dividend. The complex-dividend argument contains a floating-point complex value. For OTS$DIVC, complex-dividend is an F-floating complex number. For OTS$DIVCD_R3, complex-dividend is a D-floating complex number. For OTS$DIVCG_R3, complex-dividend is a G-floating complex number. For OTS$DIVCT_R3, complex-dividend is an IEEE T-floating complex number.

complex-divisor


OpenVMS usage: complex_number
type: F_floating complex, D_floating complex, G_floating complex, IEEE S_floating complex, IEEE T_floating complex
access: read only
mechanism: by value

Complex divisor. The complex-divisor argument contains the value of the divisor. For OTS$DIVC, complex-divisor is an F-floating complex number. For OTS$DIVCD_R3, complex-divisor is a D-floating complex number. For OTS$DIVCG_R3, complex-divisor is a G-floating complex number. For OTS$DIVCS, complex-divisor is an IEEE S-floating complex number. For OTS$DIVCS, complex-dividend is an IEEE S-floating complex number. For OTS$DIVCT_R3, complex-divisor is an IEEE T-floating complex number.

Description

These routines return a complex result of a division on complex numbers.

The complex result is computed as follows:

  1. Let (a,b) represent the complex dividend.
  2. Let (c,d) represent the complex divisor.
  3. Let (r,i) represent the complex quotient.

The results of this computation are as follows:


         r = (ac + bd)/(c2 + d2)

         i = (bc - ad)/(c2 + d2)

On Alpha and I64 systems, some restrictions apply when linking OTS$DIVC or OTS$DIVCG_R3. See Chapter 1 for more information about these restrictions.


Condition Values Signaled

SS$_FLTDIV_F Arithmetic fault. Floating-point division by zero.
SS$_FLTOVF_F Arithmetic fault. Floating-point overflow.

Examples

#1

C+
C    This Fortran example forms the complex
C    quotient of two complex numbers using
C    OTS$DIVC and the Fortran random number
C    generator RAN.
C
C    Declare Z1, Z2, Z_Q, and OTS$DIVC as complex values.
C    OTS$DIVC will return the complex quotient of Z1 divided
C    by Z2:  Z_Q = OTS$DIVC( %VAL(REAL(Z1)), %VAL(AIMAG(Z1),
C    %VAL(REAL(Z2)), %VAL(AIMAG(Z2))
C-

        COMPLEX Z1,Z2,Z_Q,OTS$DIVC
C+
C    Generate a complex number.
C-
        Z1 = (8.0,4.0)
C+
C    Generate another complex number.
C-
        Z2 = (1.0,1.0)
C+
C    Compute the complex quotient of Z1/Z2.
C-
        Z_Q = OTS$DIVC( %VAL(REAL(Z1)), %VAL(AIMAG(Z1)), %VAL(REAL(Z2)),
     +                  %VAL(AIMAG(Z2)))
        TYPE *, ' The complex quotient of',Z1,' divided by ',Z2,' is'
        TYPE *, '     ',Z_Q
        END

      

This Fortran program demonstrates how to call OTS$DIVC. The output generated by this program is as follows:


The complex quotient of (8.000000,4.000000) divided by (1.000000,1.000000)
 is (6.000000,-2.000000)
#2

C+
C    This Fortran example forms the complex
C    quotient of two complex numbers by using
C    OTS$DIVCG_R3 and the Fortran random number
C    generator RAN.
C
C     Declare Z1, Z2, and Z_Q as complex values. OTS$DIVCG_R3
C     will return the complex quotient of Z1 divided by Z2:
C     Z_Q = Z1/Z2
C-

        COMPLEX*16 Z1,Z2,Z_Q
C+
C    Generate a complex number.
C-
        Z1 = (8.0,4.0)
C+
C    Generate another complex number.
C-
        Z2 = (1.0,1.0)
C+
C    Compute the complex quotient of Z1/Z2.
C-
        Z_Q = Z1/Z2
        TYPE *, ' The complex quotient of',Z1,' divided by ',Z2,' is'
        TYPE *, '     ',Z_Q
        END

      

This Fortran example uses the OTS$DIVCG_R3 entry point instead. Notice the difference in the precision of the output generated:


 The complex quotient of (8.000000000000000,4.000000000000000) divided by
(1.000000000000000,1.000000000000000) is
      (6.000000000000000,-2.000000000000000)

OTS$DIV_PK_LONG

The Packed Decimal Division with Long Divisor routine divides fixed-point decimal data, which is stored in packed decimal form, when precision and scale requirements for the quotient call for multiple precision division. The divisor must have a precision of 30 or 31 digits.

Format

OTS$DIV_PK_LONG packed-decimal-dividend ,packed-decimal-divisor ,divisor-precision ,packed-decimal-quotient ,quotient-precision ,precision-data ,scale-data


RETURNS


OpenVMS usage: cond_value
type: longword (unsigned)
access: write only
mechanism: by value


Arguments

packed-decimal-dividend


OpenVMS usage: varying_arg
type: packed decimal string
access: read only
mechanism: by reference

Dividend. The packed-decimal-dividend argument is the address of a packed decimal string that contains the shifted dividend.

Before being passed as input, the packed-decimal-dividend argument is always multiplied by 10c, where c is defined as follows:


c = 31 - prec(packed-decimal-dividend)

Multiplying packed-decimal-dividend by 10c makes packed-decimal-dividend a 31-digit number.

packed-decimal-divisor


OpenVMS usage: varying_arg
type: packed decimal string
access: read only
mechanism: by reference

Divisor. The packed-decimal-divisor argument is the address of a packed decimal string that contains the divisor.

divisor-precision


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Precision of the divisor. The divisor-precision argument is a signed word that contains the precision of the divisor. The high-order bits are filled with zeros.

packed-decimal-quotient


OpenVMS usage: varying_arg
type: packed decimal string
access: write only
mechanism: by reference

Quotient. The packed-decimal-quotient argument is the address of the packed decimal string into which OTS$DIV_PK_LONG writes the quotient.

quotient-precision


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Precision of the quotient. The quotient-precision argument is a signed word that contains the precision of the quotient. The high-order bits are filled with zeros.

precision-data


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Additional digits of precision required. The precision-data argument is a signed word that contains the value of the additional digits of precision required.

OTS$DIV_PK_LONG computes the precision-data argument as follows:


precision-data = scale(packed-decimal-quotient)
+ scale(packed-decimal-divisor)
- scale(packed-decimal-dividend)
- 31 + prec(packed-decimal-dividend)

scale-data


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Scale factor of the decimal point. The scale-data argument is a signed word that contains the scale data.

OTS$DIV_PK_LONG defines the scale-data argument as follows:


scale-data = 31 - prec(packed-decimal-divisor)


Description

On VAX systems, before using this routine, you should determine whether it is best to use OTS$DIV_PK_LONG, OTS$DIV_PK_SHORT, or the VAX instruction DIVP. To determine this, you must first calculate b, where b is defined as follows:


b = scale(packed-decimal-quotient)
+ scale(packed-decimal-divisor)
- scale(packed-decimal-dividend)
+ prec(packed-decimal-dividend)

If b is greater than 31, then OTS$DIV_PK_LONG can be used to perform the division. If b is less than 31, you could use the instruction DIVP instead.

When using this routine on an OpenVMS Alpha system, an I64 system, or on an OpenVMS VAX system and you have determined that you cannot use DIVP, you need to determine whether you should use OTS$DIV_PK_LONG or OTS$DIV_PK_SHORT. To determine this, you must examine the value of scale-data. If scale-data is less than or equal to 1, then you should use OTS$DIV_PK_LONG. If scale-data is greater than 1, you should use OTS$DIV_PK_SHORT instead.


Condition Value Signaled

SS$_FLTDIV Fatal error. Division by zero.

Example


1

    OPTION                              &
        TYPE = EXPLICIT

    !+
    !   This program uses OTS$DIV_PK_LONG to perform packed decimal
    !   division.
    !-


    !+
    !   DECLARATIONS
    !-

    DECLARE DECIMAL (31, 2)     NATIONAL_DEBT
    DECLARE DECIMAL (30, 3)     POPULATION
    DECLARE DECIMAL (10, 5)     PER_CAPITA_DEBT

    EXTERNAL SUB OTS$DIV_PK_LONG (DECIMAL(31,2), DECIMAL (30, 3), &
        WORD BY VALUE, DECIMAL(10, 5), WORD BY VALUE, WORD BY VALUE, &
        WORD BY VALUE)

    !+
    !   Prompt the user for the required input.
    !-

    INPUT   "Enter national debt: ";NATIONAL_DEBT
    INPUT   "Enter current population: ";POPULATION


    !+
    !   Perform the division and print the result.
    !
    !   scale(divd) = 2
    !   scale(divr) = 3
    !   scale(quot) = 5
    !
    !   prec(divd) = 31
    !   prec(divr) = 30
    !   prec(quot) = 10
    !
    !   prec-data  = scale(quot) + scale(divr) - scale(divd) - 31 +
    !                prec(divd)
    !   prec-data  =   5      +   3      -     2    - 31 +   31
    !   prec-data  = 6
    !
    !   b = scale(quot) + scale(divr) - scale(divd) + prec(divd)
    !   b =   5      +   3      -     2    +    31
    !   b = 37
    !
    !   c = 31 - prec(divd)
    !   c = 31 -   31
    !   c = 0
    !
    !   scale-data = 31 - prec(divr)
    !   scale-data = 31 -   30
    !   scale-data = 1
    !
    !   b is greater than 31, so either OTS$DIV_PK_LONG or
    !      OTS$DIV_PK_SHORT may be used to perform the division.
    !      If b is less than or equal to 31, then the DIVP
    !      instruction may be used.
    !
    !   scale-data is less than or equal to 1, so OTS$DIV_PK_LONG
    !      should be used instead of OTS$DIV_PK_SHORT.
    !
    !-

    CALL OTS$DIV_PK_LONG( NATIONAL_DEBT, POPULATION, '30'W, PER_CAPITA_DEBT, &
            '10'W, '6'W, '1'W)

    PRINT   "The per capita debt is ";PER_CAPITA_DEBT
    END

      

This BASIC example program uses OTS$DIV_PK_LONG to perform packed decimal division. One example of the output generated by this program is as follows:


$ RUN DEBT
Enter national debt: ?  12345678
Enter current population: ?  1212
The per capita debt is 10186.20297

OTS$DIV_PK_SHORT

The Packed Decimal Division with Short Divisor routine divides fixed-point decimal data when precision and scale requirements for the quotient call for multiple-precision division.

Format

OTS$DIV_PK_SHORT packed-decimal-dividend ,packed-decimal-divisor ,divisor-precision ,packed-decimal-quotient ,quotient-precision ,precision-data


RETURNS


OpenVMS usage: cond_value
type: longword (unsigned)
access: write only
mechanism: by value


Arguments

packed-decimal-dividend


OpenVMS usage: varying_arg
type: packed decimal string
access: read only
mechanism: by reference

Dividend. The packed-decimal-dividend argument is the address of a packed decimal string that contains the shifted dividend.

Before being passed as input, the packed-decimal-dividend argument is always multiplied by 10c, where c is defined as follows:


c = 31 - prec(packed-decimal-dividend)

Multiplying packed-decimal-dividend by 10c makes packed-decimal-dividend a 31-digit number.

packed-decimal-divisor


OpenVMS usage: varying_arg
type: packed decimal string
access: read only
mechanism: by reference

Divisor. The packed-decimal-divisor argument is the address of a packed decimal string that contains the divisor.

divisor-precision


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Precision of the divisor. The divisor-precision argument is a signed word integer that contains the precision of the divisor; high-order bits are filled with zeros.

packed-decimal-quotient


OpenVMS usage: varying_arg
type: packed decimal string
access: write only
mechanism: by reference

Quotient. The packed-decimal-quotient argument is the address of a packed decimal string into which OTS$DIV_PK_SHORT writes the quotient.

quotient-precision


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Precision of the quotient. The quotient-precision argument is a signed word that contains the precision of the quotient; high-order bits are filled with zeros.

precision-data


OpenVMS usage: word_signed
type: word (signed)
access: read only
mechanism: by value

Additional digits of precision required. The precision-data argument is a signed word that contains the value of the additional digits of precision required.

OTS$DIV_PK_SHORT computes the precision-data argument as follows:


precision-data = scale(packed-decimal-quotient)
+ scale(packed-decimal-divisor)
- scale(packed-decimal-dividend)
- 31 + prec(packed-decimal-dividend)

Description

On VAX systems, before using this routine, you should determine whether it is best to use OTS$DIV_PK_LONG, OTS$DIV_PK_SHORT, or the VAX instruction DIVP. To determine this, you must first calculate b, where b is defined as follows:


b = scale(packed-decimal-quotient) + scale(packed-decimal-divisor) -
  scale(packed-decimal-dividend) + prec(packed-decimal-dividend)

If b is greater than 31, then OTS$DIV_PK_SHORT can be used to perform the division. If b is less than 31, you could use the VAX instruction DIVP instead.

When using this routine on an OpenVMS Alpha system, an I64 system, or on an OpenVMS VAX system and you have determined that you cannot use DIVP, you need to determine whether you should use OTS$DIV_PK_LONG or OTS$DIV_PK_SHORT. To determine this, you must examine the value of scale-data. If scale-data is less than or equal to 1, then you should use OTS$DIV_PK_LONG. If scale-data is greater than 1, you should use OTS$DIV_PK_SHORT instead.


Condition Value Signaled

SS$_FLTDIV Fatal error. Division by zero.

OTS$JUMP_TO_BPV (I64 Only)

The Jump to Bound Procedure Value routine transfers control to a bound procedure.

Format

OTS$JUMP_TO_BPV bound-func-value ,standard-args ,...


RETURNS

None.


Arguments

bound-func-value


OpenVMS usage: quadword address
type: address
access: read only
mechanism: by value in register R1 (GP)

Function value for the procedure being called.

standard-args


type:
access:

Zero or more arguments to be passed to the called routine, passed using standard conventions (including the AI register).

Description

When a procedure value that refers to a bound procedure descriptor is used to make a call, the routine designated in the OTS_ENTRY field (typically OTS$JUMP_TO_BPV) receives control with the GP register pointing to the bound procedure descriptor (instead of a global offset table). This routine performs the following steps:
  1. Load the "real" target entry address into a volatile branch register, for example, B6.
  2. Load the dynamic environment value into the appropriate uplevel-addressing register for the target function, for example, OTS$JUMP_TO_BPV uses R9.
  3. Load the "real" target GP address into the GP register
  4. Transfer control (branch, not call) to the target entry address.

Control arrives at the real target procedure address with both the GP and environment register values established appropriately.

Support routine OTS$JUMP_TO_BPV is included as a standard library routine. The operation of OTS$JUMP_TO_BPV is logically equivalent to the following code:


   OTS$JUMP_TO_BPV::
        add     gp=gp,24        ; Adjust GP to point to entry address
        ld8     r9=[gp],16      ; Load target entry address
        mov     b6=r9
        ld8     r9=[gp],-8      ; Load target environment value
        ld8     gp=[gp]         ; Load target GP
        br      b6              ; Transfer to target

Note that there can be multiple OTS$JUMP_TO_BPV-like support routines, corresponding to different target registers where the environment value should be placed. The code that creates the bound function descriptor is also necessarily compiled by the same compiler that compiles the target procedure, thus can correctly select an appropriate support routine.


Condition Values Returned

None.  


Previous Next Contents Index