Understanding the Synergy floating point API

The floating point API consists of single- and double-operand routines that enable you to perform floating-point calculations. Because DIBOL has no native floating-point data type, we have implemented this support as routines, and data (the binary representation of the double result) is stored in a8 fields.

The floating-point routines require that you follow these steps to perform floating-point calculations:

1. Initialize your floating-point a8 fields using the FP_FROM_NUM subroutine.
2. Perform the calculation using the appropriate FP_ routine.
3. Return the floating-point a8 field to usable data using the FP_TO_NUM subroutine.

Sample program

The following example contains several of the FP_ routines.

subroutine calc_stats
;Returns mean and standard deviation for a set of numbers. This routine
;requires that the set's sum and sum of squares have been calculated and
;are passed as arguments. This eliminates the need for the caller to 
;build an array of the set -- handy for report writers etc.
    a_size   ,n                  ;Number of entries
    a_sum    ,n                  ;Sum of the entries
    a_sqs    ,n                  ;Sum of the squares
    a_mean   ,n                  ;Returned mean
    a_stdd   ,n                  ;Returned standard deviation
    a_sample ,n                  ;(Optional) flag. If TRUE, requests an 
                                ; unbiased standard deviation -- use this 
                                ; if estimating for the population based on 
                                ; the sample provided.
record
    fval    ,a8
    fn_1    ,a8                 ;Needed for nonbiased calculation
    fmean   ,a8
    fsum    ,a8
    fsqs    ,a8
    fstd    ,a8

proc
    if (a_size .lt. 2)
      begin
        if (a_size .eq. 1) then
          a_mean = a_sum
        else
          a_mean = 0
        a_stdd = 0
        xreturn
      end
    ;Get count, sum and sum of squares into floating-point
    ; variables for the standard deviation calculation:
    xcall fp_from_num(fval, %implied(a_size))
    xcall fp_from_num(fsum, %implied(a_sum))
    xcall fp_from_num(fsqs, %implied(a_sqs))
    if (^passed(a_sample) .and. a_sample) then
      begin             ;Does user want a sample-based estimate?
        xcall fp_from_num(fn_1, %implied(a_size – 1))
        xcall fp_div(fsqs, fsqs, fn_1)   ;Divide by n–1 instead of n 
        xcall fp_div(fmean, fsum, fval)  ; for samples (instead of  
        xcall fp_mul(fsum, fsum, fsum)   ; the whole population).
        xcall fp_mul(fval, fval, fn_1)   ; The n-1 denominator yields
        xcall fp_div(fsum, fsum, fval)   ; a larger estimate for small
      end                                ; samples.
    else
      begin             ;This is the whole "population"
        xcall fp_div(fsqs, fsqs, fval)
        xcall fp_div(fsum, fsum, fval)
        fmean = fsum
        xcall fp_mul(fsum, fsum, fsum)
      end
    xcall fp_to_num(fmean, a_mean)
    xcall fp_sub(fval, fsqs, fsum)
    xcall fp_sqrt(fval, fval)
    xcall fp_to_num(fval, a_stdd)
    xreturn
endsubroutine