Wednesday, April 19, 2017

Min and Max built in functions added to RPG

using the rpg min and max built in functions

A pair of introductions to RPG as part of IBM i 7.3 TR2, and 7.2 TR6, are the minimum and maximum built in functions, %MIN and %MAX. The maximum built in function returns the greatest value in a list of variables and/or values. The minimum returns the lowest value from a list of variables and/or values. Otherwise the way they are defined and the rules governing them are the same.

To use these functions there must be at least two values, and they must be of the same type. What I mean is that all of the values must be some type of numeric, character, date, time, or timestamp. I cannot mix types in the values. Pointers cannot be used.

They are so simple I can go straight to examples of using them. Let me start with a variety of numeric data types:

01  dcl-s vPacked packed(5:1) inz(100.5) ;
02  dcl-s vZoned zoned(7:2) inz(9.99) ;
03  dcl-s vInteger int(10) inz(15) ;
04  dcl-s vBinary bindec(8) inz(23) ;

05  dcl-s Result packed(15:5) ;

06  Result = %max(vBinary:vInteger:vZoned:vPacked:234.5) ;
07  dsply ('Result Max = <' + %char(Result) + '>') ;

08  Result = %min(vBinary:vInteger:vZoned:vPacked:234.5) ;
09  dsply ('Result Min = <' + %char(Result) + '>') ;

Lines 1 – 4: I have four variables defined as various different types of numeric variables: packed, zoned (or signed), integer, and binary. And initialized them with different values.

Line 5: This is the variable that I am using for the returned maximum or minimum value.

Line 6: It does not matter which order these variables are placed ion the %MAX BiF (Built in Function). I have even added a constant, 234.5, as the last value. When this line is executed the largest value is returned into Result.

Line 7: I have used a Display operation code, DSPLY, to show the value of Result. As Result is a numeric variable I have to convert it to character using the Character BiF, %CHAR, so I can concatenate it in string.

Line 8: I am using the %MIN BiF with the same list as before.

Line 9: Another DSPLY to show the minimum value returned.

When I run this I see the following:

DSPLY  Result Max = <234.50000>
DSPLY  Result Min = <9.99000>

As I am comparing numbers in this example I can only use numeric types variables or constants. If I was to include another data type, say a character or date variable, I cannot compile the program as it will give me the following error:

 Msg id  Sv  Statement  Message text
*RNF0202 20     006700  OPERAND NUMBER x OF BUILT-IN FUNCTION 
                        %MAX OR %MIN CANNOT BE COMPARED TO 
                        PREVIOUS OPERANDS.

In the next example I am using characters.

01  dcl-s vOne char(15) inz('Apple') ;
02  dcl-s vTwo char(15) inz('apple') ;
03  dcl-s vThree varchar(20) inz('Blackberry') ;
04  dcl-s vFour char(15) inz('Cherry') ;

05  dcl-s Result char(20) ;

06  Result = %max(vFour:vThree:vTwo:vOne:'Banana') ;
07  dsply ('Result Max = <' + Result + '>') ;

08  Result = %min(vFour:vThree:vTwo:vOne) ;
09  dsply ('Result Min = <' + Result + '>') ;

Lines 1 – 4: In these definitions notice that line 3 is a variable length character, VARCHAR. Lines 1 and 2 will show if the sorting in these BiFs is case sensitive.

Line 5: The Result variable has to be character as a character string will be returned.

Line 6: The variables within the %MAX BiF are in no particular order, and the last value is a character string.

Line 7: I want to display what the maximum value contained within this list of values is.

Line 8: No character string in these values.

Line 9: I want to see what the lowest value is.

When run the above code the maximum value is no surprise. The minimum value shows that lower case letters are of less value than their upper case equivalents.

DSPLY  Result Max = <Cherry              >
DSPLY  Result Min = <apple               >

Dates come in a variety of different formats, but this should not be a problem for the BiFs.

01  dcl-s vDate1 date(*mdy) ;
02  dcl-s vDate2 date(*usa) ;
03  dcl-s vDate3 date(*iso) ;
04  dcl-s vDate4 date(*ymd) ;

05  dcl-s Result date ;

06  vDate1 = %date('12/25/15':*mdy/) ;
07  vDate2 = %date('12/31/2014':*usa/) ;
08  vDate3 = %date('2016-03-06':*iso-) ;
09  vDate4 = %date('77/02/21':*ymd/) ;

10  Result = %max(vDate1:vDate2:vDate3:vDate4) ;
11  dsply ('Result Max = <' + %char(Result) + '>') ;

12  Result = %min(vDate1:vDate2:vDate3:vDate4) ;
13  dsply ('Result Min = <' + %char(Result) + '>') ;

Lines 1 – 4: I have defined this date variables with different date formats.

Line 5: The Result has to be a date.

Lines 6 – 9: I am moving various dates to each of the date variables I defined in lines 1 – 4.

Line 10: Let me get the largest date.

Line 11: I want to display what the returned date is. I have to convert the date to character so that I can concatenate it into a string.

Line 12: Now for the smallest date.

Line 13: This will display the returned date.

When dates are used with these BiFs the date is returned in ISO format ( YYYY-MM-DD ).

DSPLY  Result Max = <2016-03-06>
DSPLY  Result Min = <1977-02-21>

Due to the "1940" rule used by six long dates any date with a year of 40-99 the century is '19', and years 00-39 the century is '20'. This way the year in vDate4 is 1977.

I am not going to do the same for time or timestamp fields as the rules are the same as the dates.

I can also use these BiFs when I define other variables.

01  dcl-s Array1 packed(2) dim(9) ;
02  dcl-s Array2 packed(4) dim(99) ;
03  dcl-s Array3 packed(3) 
            dim(%max(%elem(Array1):%elem(Array2))) ;

04  dcl-s NbrOfElements packed(3) 
            inz(%max(%elem(Array1):%elem(Array2))) ;

05 dsply ('Elements in Array3 = <' + %char(%elem(Array3))
           + '>') ;
06 dsply ('NbrOfElements = <' + %char(NbrOfElements) + '>') ;

Lines 1 – 3: If I want to define a third array to have the same number of elements as the larger of the other arrays.

Line 4: I can initialize a variable with the maximum number of elements in the first two arrays.

When I run this code I can see that both of these have been defined with the maximum value.

DSPLY  Elements in Array3 = <99>
DSPLY  NbrOfElements = <99>

 

You can learn more about the %MIN and %MAX built in functions from the IBM website here.

 

This article was written for IBM i 7.3 TR2, and should work for 7.2 TR6 too.

7 comments:

  1. Is it working to get %MIN-%Max of all elements of an array?

    (We do not have yet this version, so i cannot check it).

    ReplyDelete
    Replies
    1. I tried while I was writing this post and could not get it to work the way I would hope.

      Value = %min(Array) will not compile as the BiF contains too few values (needs to be more than 1).

      If you can think of any other ways to test please let me know and I will try them.

      Delete
    2. Can you do it with a dummy array? Like Value = %min(Array:Dummy). Assuming Dummy is dim(1) and initialized with *hival? Kinda goofy if it does work...

      Delete
    3. Sorry, Wally, I tried your approach too. I get a two compile errors:

      1. RNF5343 "Array ARRAY has too many omitted indexes"

      2. RNF5343 "Array DUMMY has too many omitted indexes"

      Delete
  2. In the RFE that requested %MAX and %MIN, the official IBM response mentions that %MAX(array) is not part of the enhancement, even though one of the comments for the RFE requested it.

    https://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=93114

    It says "A comment in the RFE requested that %MAX and %MIN support arrays. However, to fully support arrays, including getting the maximum or minimum value in a data structure array (the maximum or minimum of dsarray(*).subfield), the syntax would have to be quite different from the syntax for getting the minimum of a list of values. So that IBM feels that a different set of built-in functions, such as %MAXARR and %MINARR, should be used for arrays. Another RFE would be needed to provide this support for arrays."

    ReplyDelete
    Replies
    1. First, thank you Barbara for commenting on this post.

      Second of all, thank you for letting us have an insight into the (possible) future %MINARR & %MAXARR.

      Delete
    2. Someone will have to open an RFE, and lots of people will have to vote on it, before it even gets considered :-)

      Delete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.