hexagon logo

PCL; how to sort 2D array?

I am trying to sort node IDs by position. I created 2D REAL array where 1st column is node ID and second is position. Next I use mth_sort_column to sort by position column. However, it does not produce expected result. The first problem is that I cannot convert correctly INTEGER into REAL number:
 
example:
 
REAL a
INTEGER b
b=31100069
a=b
dump a, b
 
The result is:
$# REAL a = 31100068.
$# INTEGER b = 31100069
 
How to explain change of the value? How to make conversion correctly? Do I have to write my own sorting function?
Parents
  • Hi Adam,
    You have a bit of a problem trying to use 8 digit integers as a real with PCL because PCL is pretty much single precision. The language dates from the early 80's and has some limitations. To quote from the internet: "All integers with 7 or fewer decimal digits, and any 2n for a whole number −149 ≤ n ≤ 127, can be converted exactly into an IEEE 754 single-precision floating-point value." 31100069 has one too many digits to work exactly.
     
    If the model has less than 10 000 000 nodes then you can use a lookup reference to the node id to do the sort.
    (Assuming you can't just renumber all the nodes.)
    Easier to explain with an example:
    note the example writes out the sorted nodes so you may not want to run this except on a small test model with big node ids. There may be better ways of doing it but this is what sprang to mind.
     
    INTEGER nnodes
    INTEGER node_ids(VIRTUAL)
    INTEGER ref_coords(VIRTUAL)
    INTEGER analy_coords(VIRTUAL)
    INTEGER i, j
     
    REAL glob_xyzs(VIRTUAL)
    REAL sort_array(VIRTUAL)
     
    db_count_nodes( nnodes)
     
    IF (nnodes > 0) THEN
      sys_allocate_array(node_ids, 1, nnodes)
      sys_allocate_array(ref_coords, 1, nnodes)
      sys_allocate_array(analy_coords, 1, nnodes)
      sys_allocate_array(glob_xyzs,1, nnodes, 1,3)
      sys_allocate_array(sort_array,1, nnodes, 1,4)  
    ELSE
      RETURN-1
    END IF
     
    db_get_node_ids(nnodes, node_ids)
     
    db_get_nodes( nnodes, node_ids, ref_coords, analy_coords, glob_xyzs)
     
    FOR (i = 1 to nnodes)
      FOR ( j = 1 to 3)
        sort_array(i,j)=glob_xyzs(i, j)
      END FOR
      sort_array(i,4)= i 
    END FOR
     
    mth_sort_column(sort_array, 1, TRUE)
     
    FOR (i = 1 to nnodes)
      j = sort_array(i,4)
      ui_write("node:" //str_from_integer(node_ids(j))//" coords:" //@
            str_from_real(sort_array(i,1)) // " " //@
            str_from_real(sort_array(i,2)) // " " //@
            str_from_real(sort_array(i,2))  )
    END FOR
     
     
Reply
  • Hi Adam,
    You have a bit of a problem trying to use 8 digit integers as a real with PCL because PCL is pretty much single precision. The language dates from the early 80's and has some limitations. To quote from the internet: "All integers with 7 or fewer decimal digits, and any 2n for a whole number −149 ≤ n ≤ 127, can be converted exactly into an IEEE 754 single-precision floating-point value." 31100069 has one too many digits to work exactly.
     
    If the model has less than 10 000 000 nodes then you can use a lookup reference to the node id to do the sort.
    (Assuming you can't just renumber all the nodes.)
    Easier to explain with an example:
    note the example writes out the sorted nodes so you may not want to run this except on a small test model with big node ids. There may be better ways of doing it but this is what sprang to mind.
     
    INTEGER nnodes
    INTEGER node_ids(VIRTUAL)
    INTEGER ref_coords(VIRTUAL)
    INTEGER analy_coords(VIRTUAL)
    INTEGER i, j
     
    REAL glob_xyzs(VIRTUAL)
    REAL sort_array(VIRTUAL)
     
    db_count_nodes( nnodes)
     
    IF (nnodes > 0) THEN
      sys_allocate_array(node_ids, 1, nnodes)
      sys_allocate_array(ref_coords, 1, nnodes)
      sys_allocate_array(analy_coords, 1, nnodes)
      sys_allocate_array(glob_xyzs,1, nnodes, 1,3)
      sys_allocate_array(sort_array,1, nnodes, 1,4)  
    ELSE
      RETURN-1
    END IF
     
    db_get_node_ids(nnodes, node_ids)
     
    db_get_nodes( nnodes, node_ids, ref_coords, analy_coords, glob_xyzs)
     
    FOR (i = 1 to nnodes)
      FOR ( j = 1 to 3)
        sort_array(i,j)=glob_xyzs(i, j)
      END FOR
      sort_array(i,4)= i 
    END FOR
     
    mth_sort_column(sort_array, 1, TRUE)
     
    FOR (i = 1 to nnodes)
      j = sort_array(i,4)
      ui_write("node:" //str_from_integer(node_ids(j))//" coords:" //@
            str_from_real(sort_array(i,1)) // " " //@
            str_from_real(sort_array(i,2)) // " " //@
            str_from_real(sort_array(i,2))  )
    END FOR
     
     
Children
No Data