• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Answered Variablelengthencoding Function Not Working

Cecil

17+ years progress programming and still learning.
#1
I writing a Variable Length Encoding function based on some Java code. it looks quite simple but I get different results.

Here is the original Java Code:
Code:
public class VariableLengthEncoding {
   
    public static Vector encodeValue(int value) {
        Vector<Integer> digits = new Vector();

        do {
            int digit = value % 128;
            value = value / 128;
            // if there are more digits to encode, set the top bit of this digit
            if ( value > 0 ) {
              digit = digit | 0x80;
            }
           
            digits.add(digit);
        }
        while ( value > 0 );
       
        return digits;
    }
}
Here is my ABL code equivalent:

Code:
FUNCTION bitWiseOR RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
   DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
   DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
   DEFINE VARIABLE n  AS INTEGER NO-UNDO.
   DEFINE VARIABLE Z  AS INTEGER NO-UNDO.

   DO n = 1 TO 32:
     ASSIGN
       b1 = GET-BITS(X, n, 1)
       b2 = GET-BITS(Y, n, 1)
       .
       IF b1 = 1 OR b2 = 1 THEN PUT-BITS(Z, n, 1) = 1.
   END.

   RETURN Z.
END FUNCTION.

function variableLengthEncoding returns character(input x as integer):

    define variable encodeByte     as integer   no-undo.
    define variable encodeBytes    as character no-undo.
    define variable encodeByteRaw as raw       no-undo.

    do while x > 0:
       
        encodeByte = x mod 128.
       
        x = x / 128.
       
        /** if there are more digits to encode, set the top bit of this digit **/
        if (x > 0) then
            put-byte(encodeByteRaw, 1) = bitWiseOR(input encodeByte, input 0x80).
 
        encodeBytes = encodeBytes + ",0x" + caps(hex-encode(encodeByteRaw)).
       
    end.
   
    encodeBytes = left-trim(encodeBytes , ',').
   
    return encodeBytes.
end.  

message VariableLengthEncoding (INPUT 268435455).
When encoding 268435455 it should return "0xFF, 0xFF, 0xFF, 0x7F" but it return "0xFF,0x80,0x80,0x80,0x00" why would that be?
 
Last edited:

Cecil

17+ years progress programming and still learning.
#2
I think the problem might be with "x = x / 128." where the value of the expression is being rounded to fit into a integer. However I not positive that I know how to fix this.

I was hoping "x = truncate(x / 128, 0)." would fix it, but nooo. Doh!
 
Last edited:

Cecil

17+ years progress programming and still learning.
#3
I belive I've found the solution:

Code:
FUNCTION bitWiseOR RETURNS INTEGER (INPUT X AS INTEGER, INPUT Y AS INTEGER):
   DEFINE VARIABLE b1 AS INTEGER NO-UNDO.
   DEFINE VARIABLE b2 AS INTEGER NO-UNDO.
   DEFINE VARIABLE n  AS INTEGER NO-UNDO.
   DEFINE VARIABLE Z  AS INTEGER NO-UNDO.

   DO n = 1 TO 32:
     ASSIGN
       b1 = GET-BITS(X, n, 1)
       b2 = GET-BITS(Y, n, 1)
       .
       IF b1 = 1 OR b2 = 1 THEN PUT-BITS(Z, n, 1) = 1.
   END.

   RETURN Z.
END FUNCTION.

DEFINE VARIABLE iexp AS INT EXTENT 16 INITIAL [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 ].

FUNCTION RightShift returns INTEGER ( i_ivalue AS INTEGER, i_ishift AS INTEGER ):

    RETURN INTEGER( TRUNCATE( i_ivalue / iexp[ i_ishift + 1], 0 ) ).

END function.

function variableLengthEncoding returns character(input x as integer   ):

    define variable encodeByte     as integer   no-undo.
    define variable encodeBytes    as character no-undo.
    define variable encodeByteRaw as raw       no-undo.
    
    do while x > 127 :
        
        put-byte(encodeByteRaw, 1) = bitWiseOR(input x, input 0x80).
 
        encodeBytes = encodeBytes + ",0x" + caps(hex-encode(encodeByteRaw)).
        
        x = RightShift(x,7).
        
    end.
    
    put-byte(encodeByteRaw, 1) = x.
 
    encodeBytes = encodeBytes + ",0x" + caps(hex-encode(encodeByteRaw)).

    encodeBytes = left-trim(encodeBytes , ',').
    
    return encodeBytes.
end.   

message VariableLengthEncoding (INPUT 0).
message VariableLengthEncoding (INPUT 127).
message VariableLengthEncoding (INPUT 128).
message VariableLengthEncoding (INPUT 16383).
message VariableLengthEncoding (INPUT 2097151).
message VariableLengthEncoding (INPUT 2097152).
message VariableLengthEncoding (INPUT 268435455).
 

Cringer

ProgressTalk.com Moderator
Staff member
#4
I think the problem might be with "x = x / 128." where the value of the expression is being rounded to fit into a integer. However I not positive that I know how to fix this.

I was hoping "x = truncate(x / 128, 0)." would fix it, but nooo. Doh!
Truncate only works on decimal values.

Code:
define variable x as integer     no-undo.
define variable y as decimal     no-undo.

assign 
    x = 127
    y = 127. 

assign 
    x = x / 128
    y = y / 128.

message x truncate(y,0)
    view-as alert-box info buttons ok.
So if you do your work in a decimal field which you always truncate to 0, and then int() the value before you use it, then you should be good to go.
 

Cecil

17+ years progress programming and still learning.
#6
In the the end I looked for other sample code and I changed the code to not use the dividing method, but to change to a bit shift.
 

Cecil

17+ years progress programming and still learning.
#7
Truncate only works on decimal values.

Code:
define variable x as integer     no-undo.
define variable y as decimal     no-undo.

assign
    x = 127
    y = 127.

assign
    x = x / 128
    y = y / 128.

message x truncate(y,0)
    view-as alert-box info buttons ok.
So if you do your work in a decimal field which you always truncate to 0, and then int() the value before you use it, then you should be good to go.
I should of said that I was tinkering with the code and i changed the 'x' variable to a decimal so I could use TRUNCATE function.