73
73
#include <stdio.h>
74
74
#include <time.h>
75
75
76
+ // FLOAT16 credits: Steven Pigeon
77
+ // https://hbfs.wordpress.com/2013/02/12/float16/
78
+ typedef union {
79
+ // float16 v;
80
+ struct {
81
+ // type determines alignment!
82
+ u16 m : 10 ;
83
+ u16 e : 5 ;
84
+ u16 s : 1 ;
85
+ } bits ;
86
+ struct {
87
+ u8 low ;
88
+ u8 high ;
89
+ } bytes ;
90
+ } float16_s ;
91
+
92
+ typedef union {
93
+ float v ;
94
+ struct {
95
+ u32 m : 23 ;
96
+ u32 e : 8 ;
97
+ u32 s : 1 ;
98
+ } bits ;
99
+ } float32_s ;
100
+
101
+ float float16to32 (float16_s f16 ) {
102
+ // back to 32
103
+ float32_s f32 ;
104
+ f32 .bits .s = f16 .bits .s ;
105
+ f32 .bits .e = (f16 .bits .e - 15 ) + 127 ; // safe in this direction
106
+ f32 .bits .m = ((u32 )f16 .bits .m ) << 13 ;
107
+ return f32 .v ;
108
+ }
109
+
110
+
76
111
#define ASSERT_SI_RANGE (v , n ) if (VAL_INT64(v) < (- (i64)n) || VAL_INT64(v) > (i64)n) Trap1(RE_OUT_OF_RANGE, v);
77
112
#define ASSERT_UI_RANGE (v , n ) if (VAL_INT32(v) > n) Trap1(RE_OUT_OF_RANGE, v);
78
113
#define ASSERT_UIBYTES_RANGE (v , n ) if (VAL_LEN(v) > n) Trap1(RE_OUT_OF_RANGE, v);
@@ -141,6 +176,8 @@ static REBCNT EncodedU32_Size(u32 value) {
141
176
// code [word! block!] "Input encoding"
142
177
// /into "Put READ results in out block, instead of creating a new block"
143
178
// out [block!] "Target block for results, when /into is used"
179
+ // /with "Additional input argument"
180
+ // num [integer!] "Bits/bytes number used with WORD! code type to resolve just single value"
144
181
// ]
145
182
***********************************************************************/
146
183
{
@@ -153,6 +190,8 @@ static REBCNT EncodedU32_Size(u32 value) {
153
190
REBVAL * val_read = D_ARG (7 );
154
191
REBOOL ref_into = D_REF (8 );
155
192
REBVAL * val_into = D_ARG (9 );
193
+ REBOOL ref_with = D_REF (10 );
194
+ REBVAL * val_num = D_ARG (11 );
156
195
157
196
REBVAL * ret = D_RET ;
158
197
//REBVAL *buf;
@@ -766,6 +805,7 @@ static REBCNT EncodedU32_Size(u32 value) {
766
805
// if encoding is just a word, simulate block with single value on stack
767
806
DS_PUSH (val_read );
768
807
value = DS_TOP ;
808
+ if (IS_INTEGER (val_num )) DS_PUSH (val_num );
769
809
DS_PUSH_END ; // marks end of the block
770
810
if (ref_into ) {
771
811
blk = VAL_SERIES (val_into );
@@ -778,12 +818,14 @@ static REBCNT EncodedU32_Size(u32 value) {
778
818
DS_PUSH_NONE ;
779
819
temp = DS_TOP ;
780
820
REBINT ssp = DSP ; // starting stack pointer
821
+ REBINT cmd ;
781
822
782
823
for (; NOT_END (value ); value ++ ) {
783
824
n = 0 ;
784
825
switch (VAL_TYPE (value )) {
785
826
case REB_WORD :
786
- switch (VAL_WORD_CANON (value )) {
827
+ cmd = VAL_WORD_CANON (value );
828
+ switch (cmd ) {
787
829
case SYM_UI8 :
788
830
n = 1 ;
789
831
ASSERT_READ_SIZE (value , cp , ep , n );
@@ -810,6 +852,12 @@ static REBCNT EncodedU32_Size(u32 value) {
810
852
VAL_SET (temp , REB_INTEGER );
811
853
SET_INT32 (temp , (i16 )((i16 )cp [1 ] + ((i16 )cp [0 ] << 8 )));
812
854
break ;
855
+ case SYM_SI16LE :
856
+ n = 2 ;
857
+ ASSERT_READ_SIZE (value , cp , ep , n );
858
+ VAL_SET (temp , REB_INTEGER );
859
+ SET_INT32 (temp , (i16 )((i16 )cp [0 ] + ((i16 )cp [1 ] << 8 )));
860
+ break ;
813
861
case SYM_UI24 :
814
862
case SYM_UI24BE :
815
863
n = 3 ;
@@ -967,48 +1015,55 @@ static REBCNT EncodedU32_Size(u32 value) {
967
1015
if (IS_GET_WORD (next )) next = Get_Var (next );
968
1016
if (!IS_INTEGER (next )) Trap1 (RE_INVALID_SPEC , value );
969
1017
i = 0 ;
970
- if (inBit == 0 ) inBit = 0x80 ;
971
1018
// could be optimized?
972
1019
nbits = VAL_INT32 (next );
973
1020
//printf("bits: %i %i\n", nbits, 1 << nbits);
974
- nbits = 1 << nbits ;
975
- ASSERT_READ_SIZE (value , cp , ep , 1 );
976
- while (nbits > 1 ) {
977
- nbits = nbits >> 1 ;
978
- if (IS_BIT_SET (cp [0 ], inBit )) i = i | nbits ;
979
- //printf("?? %i %i\n", inBit, i);
980
- NEXT_IN_BIT (inBit );
981
- //printf("inBit: %i\n", inBit);
1021
+ if (nbits > 0 ) {
1022
+ if (inBit == 0 ) inBit = 0x80 ;
1023
+ nbits = 1 << nbits ;
1024
+ ASSERT_READ_SIZE (value , cp , ep , 1 );
1025
+ while (nbits > 1 ) {
1026
+ nbits = nbits >> 1 ;
1027
+ if (IS_BIT_SET (cp [0 ], inBit )) i = i | nbits ;
1028
+ //printf("?? %i %i\n", inBit, i);
1029
+ NEXT_IN_BIT (inBit );
1030
+ //printf("inBit: %i\n", inBit);
1031
+ }
1032
+ STORE_IN_BIT (val_ctx , inBit );
982
1033
}
983
1034
VAL_SET (temp , REB_INTEGER );
984
1035
SET_INT32 (temp , i );
985
- STORE_IN_BIT (val_ctx , inBit );
986
1036
break ;
987
1037
case SYM_SB :
1038
+ case SYM_FB :
988
1039
next = ++ value ;
989
1040
if (IS_GET_WORD (next )) next = Get_Var (next );
990
1041
if (!IS_INTEGER (next )) Trap1 (RE_INVALID_SPEC , value );
991
- i = 0 ;
992
- if (inBit == 0 ) inBit = 0x80 ;
1042
+ u = 0 ;
993
1043
// could be optimized?
994
1044
nbits = VAL_INT32 (next );
995
- nbits = 1 << nbits ;
996
1045
if (nbits > 0 ) {
997
- //printf("nbits: %i\n", nbits);
998
- ASSERT_READ_SIZE (value , cp , ep , 1 );
999
- BOOL negative = IS_BIT_SET (cp [0 ], inBit );
1000
- nbits = nbits >> 1 ;
1001
- NEXT_IN_BIT (inBit );
1002
- while (nbits > 1 ) {
1003
- nbits = nbits >> 1 ;
1004
- if (IS_BIT_SET (cp [0 ], inBit )) i = i | nbits ;
1005
- //printf("?? %i %i\n", inBit, i);
1006
- NEXT_IN_BIT (inBit );
1007
- }
1008
- if (negative ) i = - i ;
1046
+ if (inBit == 0 ) inBit = 0x80 ;
1047
+ // http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
1048
+ u64 m = 1U << (nbits - 1 ); // sign bit mask
1049
+ nbits = 1 << nbits ;
1050
+ //if (nbits > 0) {
1051
+ //printf("SB nbits: %i\n", nbits);
1052
+ while (nbits > 1 ) {
1053
+ nbits >>= 1 ;
1054
+ if (IS_BIT_SET (cp [0 ], inBit )) u = u | nbits ;
1055
+ //printf("?? %i %i %u\n", nbits, inBit, u);
1056
+ NEXT_IN_BIT (inBit );
1057
+ }
1058
+ u = (u ^ m ) - m ;
1059
+ //}
1060
+ STORE_IN_BIT (val_ctx , inBit );
1061
+ }
1062
+ if (cmd == SYM_SB ) {
1063
+ SET_INTEGER (temp , u );
1064
+ } else {
1065
+ SET_DECIMAL (temp , (double )u / 65536.0 );
1009
1066
}
1010
- VAL_SET (temp , REB_INTEGER );
1011
- SET_INT32 (temp , i );
1012
1067
break ;
1013
1068
case SYM_BIT :
1014
1069
case SYM_NOT_BIT :
@@ -1027,7 +1082,8 @@ static REBCNT EncodedU32_Size(u32 value) {
1027
1082
break ;
1028
1083
case SYM_ALIGN :
1029
1084
// aligns bit buffer to byte boundary
1030
- if (inBit > 0 ) {
1085
+ //if (inBit == 128) inBit = 0;
1086
+ if (inBit > 0 && inBit < 128 ) {
1031
1087
inBit = 0 ;
1032
1088
cp ++ ;
1033
1089
VAL_INDEX (buffer_read )++ ;
@@ -1145,10 +1201,75 @@ static REBCNT EncodedU32_Size(u32 value) {
1145
1201
VAL_INDEX (buffer_read ) = i ; //TODO: range test
1146
1202
cp = BIN_DATA (bin ) + VAL_INDEX (buffer_read );
1147
1203
continue ;
1204
+ case SYM_SKIPBITS :
1205
+ next = ++ value ;
1206
+ if (IS_GET_WORD (next )) next = Get_Var (next );
1207
+ if (!IS_INTEGER (next )) Trap1 (RE_INVALID_SPEC , value );
1208
+ i = VAL_INT32 (next );
1209
+ if (i >= 8 ) {
1210
+ i /= 8 ;
1211
+ //printf("byte skip: %d\n", i);
1212
+ ASSERT_READ_SIZE (value , cp , ep , i );
1213
+ cp += i ;
1214
+ VAL_INDEX (buffer_read ) += i ;
1215
+ i = VAL_INT32 (next ) - (i * 8 );
1216
+ }
1217
+ if (inBit == 0 ) inBit = 0x80 ;
1218
+ while (i > 0 ) {
1219
+ i -- ;
1220
+ //printf("inbit %d: %d %d\n",i, inBit, VAL_INDEX(buffer_read));
1221
+ NEXT_IN_BIT (inBit );
1222
+ }
1223
+ continue ;
1148
1224
case SYM_LENGTHQ :
1149
1225
VAL_SET (temp , REB_INTEGER );
1150
1226
SET_INT32 (temp , VAL_TAIL (buffer_read ) - VAL_INDEX (buffer_read ));
1151
1227
break ;
1228
+ case SYM_TUPLE3 :
1229
+ n = 3 ;
1230
+ goto readNTuple ;
1231
+ case SYM_TUPLE4 :
1232
+ n = 4 ;
1233
+ readNTuple :
1234
+ ASSERT_READ_SIZE (value , cp , ep , n );
1235
+ Set_Tuple (temp , BIN_DATA (bin ) + VAL_INDEX (buffer_read ), n );
1236
+ break ;
1237
+ case SYM_FLOAT16 :
1238
+ n = 2 ;
1239
+ ASSERT_READ_SIZE (value , cp , ep , n );
1240
+ float16_s f16 ;
1241
+ f16 .bytes .low = cp [0 ];
1242
+ f16 .bytes .high = cp [1 ];
1243
+ SET_DECIMAL (temp , float16to32 (f16 ) );
1244
+ break ;
1245
+ case SYM_FLOAT :
1246
+ n = 4 ;
1247
+ ASSERT_READ_SIZE (value , cp , ep , n );
1248
+ SET_DECIMAL (temp , ((float * )cp )[0 ]);
1249
+ break ;
1250
+ case SYM_DOUBLE :
1251
+ n = 8 ;
1252
+ ASSERT_READ_SIZE (value , cp , ep , n );
1253
+ SET_DECIMAL (temp , ((double * )cp )[0 ]);
1254
+ break ;
1255
+ case SYM_FIXED8 :
1256
+ n = 2 ;
1257
+ ASSERT_READ_SIZE (value , cp , ep , n );
1258
+ i = ((i32 )cp [0 ] << 0 ) |
1259
+ ((i32 )cp [1 ] << 8 ) ;
1260
+ SET_DECIMAL (temp , (float )i / 256.0f );
1261
+ break ;
1262
+ case SYM_FIXED16 :
1263
+ n = 4 ;
1264
+ ASSERT_READ_SIZE (value , cp , ep , n );
1265
+ i = ((i32 )cp [0 ] << 0 ) |
1266
+ ((i32 )cp [1 ] << 8 ) |
1267
+ ((i32 )cp [2 ] << 16 ) |
1268
+ ((i32 )cp [3 ] << 24 ) ;
1269
+ VAL_SET (temp , REB_DECIMAL );
1270
+ VAL_DECIMAL (temp ) = ((float )i / 65536.0f );
1271
+ break ;
1272
+
1152
1273
default :
1153
1274
Trap1 (RE_INVALID_SPEC , value );
1154
1275
}
@@ -1184,6 +1305,8 @@ static REBCNT EncodedU32_Size(u32 value) {
1184
1305
DS_DROP ; // temp
1185
1306
DS_DROP ; // END of the virtual block
1186
1307
DS_DROP ; // value
1308
+ if (IS_INTEGER (val_num )) DS_DROP ;
1309
+ //@@ could above be done better?
1187
1310
}
1188
1311
1189
1312
if (ref_into ) * ret = * val_into ;
0 commit comments