Hi
Recently I posted some questions concerning problems with 16 bit sets. I got good suggestions from some of you, but further analysis of the code revealed this kind of construct: **************************** TYPE INT16 = INTEGER(16); INT8 = packed 0.. INT0_65535 = packed 0..65535; B_TYPE = (B1, B2, B3, B4, B5, B6, B7, B8); BITS = (BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7,BIT8,BIT9,
BIT10,BIT11,BIT12,BIT13,BIT14,BIT15); B_TYPE_SET = set of B_TYPE; BIT_SET = set of BITS;
VAR OUT_REC = record case INT16 of 0 : (BSLB: B_TYPE_SET; BSHB: B_TYPE_SET); 1 : (USRINT : INT0_65535); 2 : (BT: BIT_SET); END;
****************************** The code heavily depends on the record variants to be aligned exactly on top of each other.
Is there anyone in the GPC project that is working, or planning to work,
on this issue? ("optimized set constructor"??) How long would it take? The company I'm working for, HiQ Approve AB, is willing to discuss a financial contribution to get this done.
Best Regards
Sven Jauring
Sven Jauring wrote:
Recently I posted some questions concerning problems with 16 bit sets. I got good suggestions from some of you, but further analysis of the code revealed this kind of construct:
TYPE INT16 = INTEGER(16); INT8 = packed 0.. INT0_65535 = packed 0..65535; B_TYPE = (B1, B2, B3, B4, B5, B6, B7, B8); BITS = (BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7,BIT8,BIT9,
BIT10,BIT11,BIT12,BIT13,BIT14,BIT15); B_TYPE_SET = set of B_TYPE; BIT_SET = set of BITS;
VAR OUT_REC = record case INT16 of 0 : (BSLB: B_TYPE_SET; BSHB: B_TYPE_SET); 1 : (USRINT : INT0_65535); 2 : (BT: BIT_SET); END;
The code heavily depends on the record variants to be aligned exactly on top of each other.
Is there anyone in the GPC project that is working, or planning to work,
on this issue? ("optimized set constructor"??) How long would it take? The company I'm working for, HiQ Approve AB, is willing to discuss a financial contribution to get this done.
I haven't followed the thread too intensely since I was out of town last week. If I understand it correctly, what you need is that a set of a type of, say 8, elements is only 1 byte large. (However, in the code above, there will also be endianness problems, i.e. on a little-endian system BSLB would align with the least significant bits of USRINT and on a big-endian system with the most significant bits; this problem could be overcome with a conditional compilation, see, e.g., the declaration of TWindowXY in GPC's CRT unit).
GPC internally stores sets as arrays of a certain type, currently MedCard. It is fairly easy to change that type to Byte (requires a small change in p/rts/sets.pas (TSelElement) and two in p/util.c (set_word_size and set_alignment)).
However note:
- This will slightly decrease the performance of set routines since they will use byte rather than word operations internally.
- Sets with and without this change will be incompatible. Don't try to mix object files created by a patched and an unpatched compiler.
- This works only down to bytes. Trying even smaller types (like Cardinal (4)) there will not work.
Another approach would be to keep the array of words for sets at least as big as a word, and use a single smaller type for smaller sets. Then they would take only as many bits as required within a packed record. However, this would require quite some effort. Basically, every set operation would have to check if their arguemnts are of the second type and convert them, and likewise convert back the result.
Personally, I'd suggest to change your Pascal code to not rely on the variant alignment and such ...
Frank
Hi Frank
Thank you for your help. I modifed the compiler according to your instructions so that it uses Byte instead of MedCard for sets. It worked wonders for the two 8 bit sets. (BSLB and BSHB in my example code below). Unfortunately I ran into trouble with the 16 bit sets.
I need BIT0 to represent the least and BIT15 the most significant bit, but since the 16 bit set is split into two bytes, BIT8 represents the least and BIT7 the most significant bit:
+-----+---+----+-----+---+----+ USRINT |bit15|...|bit8|bit7 |...|bit0| +-----+---+----+-----+---+----+ BT |BIT7 |...|BIT0|BIT15|...|BIT8| +-----+---+----+-----+---+----+
This seems like some sort of LittleEndianness? Is it possible to have the byte order shifted, so that USRINT and BT aligns?
I can't just change the order of declaration for BITS, e.g BITS=(BIT8,...,BIT15,...,BIT0,...,BIT7), since that would "undermine" the use of ord() and subsets (e.g [BIT6..BIT8]).
The Pascal code that I need to compile is not actually ours, so any changes to the code has to be done everytime a new version is released. (It is also rather large...) The code would not have had this kind of contructions had it been ours. ;-)
Best Regards Sven Jauring
Frank Heckenbach wrote:
Sven Jauring wrote:
Recently I posted some questions concerning problems with 16 bit sets. I got good suggestions from some of you, but further analysis of the code revealed this kind of construct:
TYPE INT16 = INTEGER(16); INT8 = packed 0.. INT0_65535 = packed 0..65535; B_TYPE = (B1, B2, B3, B4, B5, B6, B7, B8); BITS = (BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7,BIT8,BIT9,
BIT10,BIT11,BIT12,BIT13,BIT14,BIT15); B_TYPE_SET = set of B_TYPE; BIT_SET = set of BITS;
VAR OUT_REC = record case INT16 of 0 : (BSLB: B_TYPE_SET; BSHB: B_TYPE_SET); 1 : (USRINT : INT0_65535); 2 : (BT: BIT_SET); END;
I haven't followed the thread too intensely since I was out of town last week. If I understand it correctly, what you need is that a set of a type of, say 8, elements is only 1 byte large. (However, in the code above, there will also be endianness problems, i.e. on a little-endian system BSLB would align with the least significant bits of USRINT and on a big-endian system with the most significant bits; this problem could be overcome with a conditional compilation, see, e.g., the declaration of TWindowXY in GPC's CRT unit).
GPC internally stores sets as arrays of a certain type, currently MedCard. It is fairly easy to change that type to Byte (requires a small change in p/rts/sets.pas (TSelElement) and two in p/util.c (set_word_size and set_alignment)).
However note:
This will slightly decrease the performance of set routines since they will use byte rather than word operations internally.
Sets with and without this change will be incompatible. Don't try to mix object files created by a patched and an unpatched compiler.
This works only down to bytes. Trying even smaller types (like Cardinal (4)) there will not work.
Another approach would be to keep the array of words for sets at least as big as a word, and use a single smaller type for smaller sets. Then they would take only as many bits as required within a packed record. However, this would require quite some effort. Basically, every set operation would have to check if their arguemnts are of the second type and convert them, and likewise convert back the result.
Personally, I'd suggest to change your Pascal code to not rely on the variant alignment and such ...
Frank
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/ GPC To-Do list, latest features, fixed bugs: http://agnes.dida.physik.uni-essen.de/~gnu-pascal/todo.html