source: proto/u16u8/template.c @ 602

Last change on this file since 602 was 602, checked in by cameron, 9 years ago

Compute deletion information just once.

File size: 15.4 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <stdint.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8
9#include "../lib/lib_simd.h"
10#include "../lib/block_carry.h"
11
12typedef SIMD_type BytePack;
13typedef SIMD_type BitBlock;
14
15
16// Profiling
17#if (defined(BUFFER_PROFILING) || defined(CODE_CLOCKER))
18  #include "../lib/perflib/perfsec.h"
19#endif
20
21#ifdef BUFFER_PROFILING
22BOM_Table * transcode_timer;
23#endif
24
25#ifdef CODE_CLOCKER
26        #define NUM_EVENTS 1
27        int Events[NUM_EVENTS] = {PAPI_TOT_CYC};
28        //int Events[NUM_EVENTS] = {PAPI_L2_DCM};
29        //int Events[NUM_EVENTS] = {PAPI_TOT_CYC, PAPI_BR_MSP};
30        int cal_size = 20;
31        CC * parser_timer = new CC(Events,NUM_EVENTS,cal_size);
32#endif
33
34/*===========================================================================*/
35/* UErrorCode */
36/* Extracted from ICU */
37/*===========================================================================*/
38
39typedef enum UErrorCode {
40
41    U_ZERO_ERROR              =  0,     /**< No error, no warning. */
42    U_TRUNCATED_CHAR_FOUND    = 11,     /**< Character conversion: Incomplete input sequence. */
43    U_ILLEGAL_CHAR_FOUND      = 12,     /**< Character conversion: Illegal input sequence/combination of input units. */
44} UErrorCode;
45
46typedef  uint16_t UChar;
47
48#define s2p_step(s0,s1,hi_mask,shift,p0,p1)  \
49{ \
50BitBlock t0,t1; \
51t0= simd_pack_16_hh(s0,s1) ; \
52t1= simd_pack_16_ll(s0,s1) ; \
53p0= simd_if(hi_mask,t0,simd_srli_16(t1,shift) ) ; \
54p1= simd_if(hi_mask,simd_slli_16(t0,shift) ,t1) ; \
55} \
56
57#define s2p_bytepack(s0,s1,s2,s3,s4,s5,s6,s7,p0,p1,p2,p3,p4,p5,p6,p7)  \
58{BitBlock bit00224466_0,bit00224466_1,bit00224466_2,bit00224466_3; \
59BitBlock bit11335577_0,bit11335577_1,bit11335577_2,bit11335577_3; \
60BitBlock bit00004444_0,bit22226666_0,bit00004444_1,bit22226666_1; \
61BitBlock bit11115555_0,bit33337777_0,bit11115555_1,bit33337777_1; \
62s2p_step(s0,s1,simd_himask_2,1,bit00224466_0,bit11335577_0)  \
63s2p_step(s2,s3,simd_himask_2,1,bit00224466_1,bit11335577_1)  \
64s2p_step(s4,s5,simd_himask_2,1,bit00224466_2,bit11335577_2)  \
65s2p_step(s6,s7,simd_himask_2,1,bit00224466_3,bit11335577_3)  \
66s2p_step(bit00224466_0,bit00224466_1,simd_himask_4,2,bit00004444_0,bit22226666_0)  \
67s2p_step(bit00224466_2,bit00224466_3,simd_himask_4,2,bit00004444_1,bit22226666_1)  \
68s2p_step(bit11335577_0,bit11335577_1,simd_himask_4,2,bit11115555_0,bit33337777_0)  \
69s2p_step(bit11335577_2,bit11335577_3,simd_himask_4,2,bit11115555_1,bit33337777_1)  \
70s2p_step(bit00004444_0,bit00004444_1,simd_himask_8,4,p0,p4)  \
71s2p_step(bit11115555_0,bit11115555_1,simd_himask_8,4,p1,p5)  \
72s2p_step(bit22226666_0,bit22226666_1,simd_himask_8,4,p2,p6)  \
73s2p_step(bit33337777_0,bit33337777_1,simd_himask_8,4,p3,p7)  \
74} \
75
76#define p2s_step(p0,p1,hi_mask,shift,s0,s1)  \
77{ \
78BitBlock t0,t1; \
79t0= simd_if(hi_mask,p0,simd_srli_16(p1,shift) ) ; \
80t1= simd_if(hi_mask,simd_slli_16(p0,shift) ,p1) ; \
81s0= simd_mergeh_8(t0,t1) ; \
82s1= simd_mergel_8(t0,t1) ; \
83} \
84
85#define p2s_bytemerge(p0,p1,p2,p3,p4,p5,p6,p7,s0,s1,s2,s3,s4,s5,s6,s7)  \
86{ \
87BitBlock bit00004444_0,bit22226666_0,bit00004444_1,bit22226666_1; \
88BitBlock bit11115555_0,bit33337777_0,bit11115555_1,bit33337777_1; \
89BitBlock bit00224466_0,bit00224466_1,bit00224466_2,bit00224466_3; \
90BitBlock bit11335577_0,bit11335577_1,bit11335577_2,bit11335577_3; \
91p2s_step(p0,p4,simd_himask_8,4,bit00004444_0,bit00004444_1)  \
92p2s_step(p1,p5,simd_himask_8,4,bit11115555_0,bit11115555_1)  \
93p2s_step(p2,p6,simd_himask_8,4,bit22226666_0,bit22226666_1)  \
94p2s_step(p3,p7,simd_himask_8,4,bit33337777_0,bit33337777_1)  \
95p2s_step(bit00004444_0,bit22226666_0,simd_himask_4,2,bit00224466_0,bit00224466_1)  \
96p2s_step(bit11115555_0,bit33337777_0,simd_himask_4,2,bit11335577_0,bit11335577_1)  \
97p2s_step(bit00004444_1,bit22226666_1,simd_himask_4,2,bit00224466_2,bit00224466_3)  \
98p2s_step(bit11115555_1,bit33337777_1,simd_himask_4,2,bit11335577_2,bit11335577_3)  \
99p2s_step(bit00224466_0,bit11335577_0,simd_himask_2,1,s0,s1)  \
100p2s_step(bit00224466_1,bit11335577_1,simd_himask_2,1,s2,s3)  \
101p2s_step(bit00224466_2,bit11335577_2,simd_himask_2,1,s4,s5)  \
102p2s_step(bit00224466_3,bit11335577_3,simd_himask_2,1,s6,s7)  \
103} \
104
105
106static inline void interleave4(BitBlock p0, BitBlock p1, BitBlock p2, BitBlock p3, 
107                               BitBlock& s0, BitBlock& s1, BitBlock& s2, BitBlock& s3);
108
109static inline void interleave4(BitBlock p0, BitBlock p1, BitBlock p2, BitBlock p3, 
110                               BitBlock& s0, BitBlock& s1, BitBlock& s2, BitBlock& s3){
111        BitBlock hpair0 = simd_mergel_1(p1, p0);
112        BitBlock hpair1 = simd_mergeh_1(p1, p0);
113        BitBlock lpair0 = simd_mergel_1(p3, p2);
114        BitBlock lpair1 = simd_mergeh_1(p3, p2);
115        s0 = simd_mergel_2(lpair0,hpair0);
116        s1 = simd_mergeh_2(lpair0,hpair0);
117        s2 = simd_mergel_2(lpair1,hpair1);
118        s3 = simd_mergeh_2(lpair1,hpair1);
119}
120
121
122
123
124#define do_right16_shifts(vec,rshift1,rshift2,rshift4,rshift8)  \
125{BitBlock s2; \
126vec= simd_sub_16(vec,simd_srli_16(simd_and(rshift1,vec) ,1) ) ; \
127s2= simd_and(rshift2,vec) ; \
128vec= simd_or(simd_srli_16(s2,2) ,simd_xor(vec,s2) ) ; \
129s2= simd_and(rshift4,vec) ; \
130vec= simd_or(simd_srli_16(s2,4) ,simd_xor(vec,s2) ) ; \
131s2= simd_and(rshift8,vec) ; \
132vec= simd_or(simd_srli_16(s2,8) ,simd_xor(vec,s2) ) ; \
133}
134
135static inline void delinfo_16(BitBlock & del16_rshift1, BitBlock & del16_rshift2, BitBlock & del16_rshift4,
136                              BitBlock & del16_rshift8, BitBlock delmask){
137       
138        BitBlock del16_trans2;
139        BitBlock del16_trans4;
140        BitBlock del16_trans8;
141        BitBlock shift_bits;
142       
143        del16_rshift1= simd_xor(simd_slli_16(delmask,1),simd_slli_16(delmask,2));
144        del16_rshift1= simd_xor(del16_rshift1,simd_slli_16(del16_rshift1,2));
145        del16_rshift1= simd_xor(del16_rshift1,simd_slli_16(del16_rshift1,4));
146        del16_rshift1= simd_xor(del16_rshift1,simd_slli_16(del16_rshift1,8));
147       
148        del16_trans2= simd_and(del16_rshift1,delmask);
149        del16_rshift2= simd_xor(simd_slli_16(del16_trans2,1),simd_slli_16(del16_trans2,2));
150        del16_rshift2= simd_xor(del16_rshift2,simd_slli_16(del16_rshift2,2));
151        del16_rshift2= simd_xor(del16_rshift2,simd_slli_16(del16_rshift2,4));
152        del16_rshift2= simd_xor(del16_rshift2,simd_slli_16(del16_rshift2,8));
153       
154        del16_trans4= simd_and(del16_rshift2,del16_trans2);
155        del16_rshift4= simd_xor(simd_slli_16(del16_trans4,1),simd_slli_16(del16_trans4,2));
156        del16_rshift4= simd_xor(del16_rshift4,simd_slli_16(del16_rshift4,2));
157        del16_rshift4= simd_xor(del16_rshift4,simd_slli_16(del16_rshift4,4));
158        del16_rshift4= simd_xor(del16_rshift4,simd_slli_16(del16_rshift4,8));
159       
160        del16_trans8= simd_and(del16_rshift4,del16_trans4);
161        del16_rshift8= simd_xor(simd_slli_16(del16_trans8,1),simd_slli_16(del16_trans8,2));
162        del16_rshift8= simd_xor(del16_rshift8,simd_slli_16(del16_rshift8,2));
163        del16_rshift8= simd_xor(del16_rshift8,simd_slli_16(del16_rshift8,4));
164        del16_rshift8= simd_xor(del16_rshift8,simd_slli_16(del16_rshift8,8));
165       
166        del16_rshift1= simd_andc(del16_rshift1,delmask);
167        del16_rshift2= simd_andc(del16_rshift2,delmask);
168        del16_rshift4= simd_andc(del16_rshift4,delmask);
169        del16_rshift8= simd_andc(del16_rshift8,delmask);
170       
171        del16_rshift2= simd_sub_16(del16_rshift2,simd_srli_16(simd_and(del16_rshift1,del16_rshift2),1));
172       
173        del16_rshift4= simd_sub_16(del16_rshift4,simd_srli_16(simd_and(del16_rshift1,del16_rshift4),1));
174        shift_bits= simd_and(del16_rshift2,del16_rshift4);
175        del16_rshift4= simd_or(simd_srli_16(shift_bits,2),simd_xor(del16_rshift4,shift_bits));
176       
177        del16_rshift8= simd_sub_16(del16_rshift8,simd_srli_16(simd_and(del16_rshift1,del16_rshift8),1));
178        shift_bits= simd_and(del16_rshift2,del16_rshift8);
179        del16_rshift8= simd_or(simd_srli_16(shift_bits,2),simd_xor(del16_rshift8,shift_bits)); 
180        shift_bits= simd_and(del16_rshift4,del16_rshift8);
181        del16_rshift8= simd_or(simd_srli_16(shift_bits,4),simd_xor(del16_rshift8,shift_bits));
182}
183
184static inline void bit_del_16(BitBlock &s, BitBlock del16_rshift1, BitBlock del16_rshift2, BitBlock del16_rshift4,
185                              BitBlock del16_rshift8, BitBlock delmask) {
186        s = simd_andc(s, delmask);
187        do_right16_shifts (s, del16_rshift1, del16_rshift2, del16_rshift4,  del16_rshift8);
188}
189
190
191static inline void del_count(BitBlock delmask, short *u8_bytes_per_reg){
192
193BitBlock delcounts_2;
194BitBlock delcounts_4;
195BitBlock delcounts_8;
196BitBlock delcounts_16;
197
198delcounts_2 = simd_add_2_lh(delmask, delmask);
199delcounts_4 = simd_add_4_lh(delcounts_2, delcounts_2);
200delcounts_8 = simd_add_8_lh(delcounts_4, delcounts_4);
201delcounts_16 = simd_add_16_lh(delcounts_8, delcounts_8);
202sisd_store_aligned(simd_sub_16(simd_const_16(16), delcounts_16), (BytePack *) &u8_bytes_per_reg[0]);
203}
204
205
206
207#define BLOCK_SIZE 128
208
209void u16u8(char ** targetbuf, const char * targetlimit, const UChar ** srcbuf, const UChar * srclimit, UErrorCode * err){
210
211  @decl
212
213SIMD_type u16l [8];
214SIMD_type u16h [8];
215
216
217  BytePack * U16;
218  BytePack U16h[8];
219  BytePack U16l[8];
220
221  BitBlock doublepair[32];
222
223  BitBlock endmask;
224
225  BitBlock delmask[4];
226
227  BitBlock U8[32];
228
229  int target_bckup_steps = 0;
230  int pos = 0;
231
232  intptr_t  units_remaining  = 0;
233  intptr_t  units_read  = 0;
234
235  bool error_found = false;
236  int err_pos;
237
238  @stream_stmts
239
240  do {
241   
242    PERF_SEC_START(transcode_timer);
243
244    U16 = (BytePack *)(*srcbuf);
245    units_remaining = srclimit-(*srcbuf);
246
247    if(units_remaining < BLOCK_SIZE){
248        endmask = sisd_sll(simd_const_1(1),sisd_from_int((int) units_remaining));
249        units_read = units_remaining;
250
251//      ((uint16_t *) U16)[units_read/2] = 0;
252    }
253    else {
254        endmask = simd_const_1(0);
255        units_read = BLOCK_SIZE;
256    }
257
258    for (int i=0; i< 8; i++){
259      U16h[i] = simd_pack_16_ll(sisd_load_unaligned(&U16[i*2+1]),sisd_load_unaligned(&U16[i*2]));
260      U16l[i] = simd_pack_16_hh(sisd_load_unaligned(&U16[i*2+1]),sisd_load_unaligned(&U16[i*2]));
261    }
262
263
264    s2p_bytepack(U16h[7], U16h[6], U16h[5], U16h[4], U16h[3], U16h[2], U16h[1], U16h[0],
265    u16h[0], u16h[1], u16h[2], u16h[3], u16h[4], u16h[5], u16h[6], u16h[7]);
266
267    s2p_bytepack(U16l[7], U16l[6], U16l[5], U16l[4], U16l[3], U16l[2], U16l[1], U16l[0],
268    u16l[0], u16l[1], u16l[2], u16l[3], u16l[4], u16l[5], u16l[6], u16l[7]);
269
270array_u16l__0_ = u16l [0];
271array_u16l__1_ = u16l [1];
272array_u16l__2_ = u16l [2];
273array_u16l__3_ = u16l [3];
274array_u16l__4_ = u16l [4];
275array_u16l__5_ = u16l [5];
276array_u16l__6_ = u16l [6];
277array_u16l__7_ = u16l [7];
278
279array_u16h__0_ = u16h [0];
280array_u16h__1_ = u16h [1];
281array_u16h__2_ = u16h [2];
282array_u16h__3_ = u16h [3];
283array_u16h__4_ = u16h [4];
284array_u16h__5_ = u16h [5];
285array_u16h__6_ = u16h [6];
286array_u16h__7_ = u16h [7];
287
288    @block_stmts
289
290/* Convert flattened array values to arrays */
291SIMD_type u8_pre [8];
292u8_pre[0] = array_u8_pre__0_;
293u8_pre[1] = array_u8_pre__1_;
294u8_pre[2] = array_u8_pre__2_;
295u8_pre[3] = array_u8_pre__3_;
296u8_pre[4] = array_u8_pre__4_;
297u8_pre[5] = array_u8_pre__5_;
298u8_pre[6] = array_u8_pre__6_;
299u8_pre[7] = array_u8_pre__7_;
300
301SIMD_type u8_butlast [8];
302u8_butlast[0] = array_u8_butlast__0_;
303u8_butlast[1] = array_u8_butlast__1_;
304u8_butlast[2] = array_u8_butlast__2_;
305u8_butlast[3] = array_u8_butlast__3_;
306u8_butlast[4] = array_u8_butlast__4_;
307u8_butlast[5] = array_u8_butlast__5_;
308u8_butlast[6] = array_u8_butlast__6_;
309u8_butlast[7] = array_u8_butlast__7_;
310
311SIMD_type u8_last [8];
312u8_last[0] = array_u8_last__0_;
313u8_last[1] = array_u8_last__1_;
314u8_last[2] = array_u8_last__2_;
315u8_last[3] = array_u8_last__3_;
316u8_last[4] = array_u8_last__4_;
317u8_last[5] = array_u8_last__5_;
318u8_last[6] = array_u8_last__6_;
319u8_last[7] = array_u8_last__7_;
320
321
322    if (bitblock_has_bit(strct_u16__error_)) {
323       
324       err_pos = count_forward_zeroes(strct_u16__error_);
325       error_found = true;
326        if ((err_pos == units_read)) {
327                err_pos--;
328                *err = U_TRUNCATED_CHAR_FOUND;
329                (*srcbuf) += err_pos;
330                if(err_pos<0){
331                        target_bckup_steps = 2;
332                        (*targetbuf) -= target_bckup_steps;
333                        return;
334                }               
335        }
336        else {
337          if((((unsigned char *)U16h)[err_pos]< 0xDC) || (((unsigned char *)U16h)[err_pos] >= 0xE0))
338                err_pos--;
339                *err = U_ILLEGAL_CHAR_FOUND;
340                (*srcbuf) += err_pos;
341                if(err_pos<0){
342                        target_bckup_steps = 2;
343                        (*targetbuf) -= target_bckup_steps;
344                        return;
345                }
346        }
347        endmask = sisd_sll(simd_const_1(1),sisd_from_int(err_pos));
348    }
349
350    for (int i=0; i< 8; i++){
351        interleave4(simd_const_8(0), u8_pre[i], u8_butlast[i], u8_last[i],
352                                doublepair[i*4], doublepair[i*4+1], 
353                                doublepair[i*4+2], doublepair[i*4+3]);
354    }
355
356        interleave4(simd_const_1(1), simd_or(endmask, simd_not(strct_u16__utf8_3_)), 
357                                simd_or(endmask, strct_u16__ASCII_), endmask,
358                                delmask[0], delmask[1], delmask[2], delmask[3]);
359
360
361
362     BitBlock shft1, shft2, shft3, shft4;
363     delinfo_16(shft1, shft2, shft3, shft4, delmask[0]);
364     for (int i=0; i< 32; i=i+4){
365        bit_del_16(doublepair[i],shft1, shft2, shft3, shft4, delmask[0]);
366     }
367     delinfo_16(shft1, shft2, shft3, shft4, delmask[1]);
368     for (int i=0; i< 32; i=i+4){
369        bit_del_16(doublepair[i+1],shft1, shft2, shft3, shft4, delmask[1]);
370     }
371     delinfo_16(shft1, shft2, shft3, shft4, delmask[2]);
372     for (int i=0; i< 32; i=i+4){
373        bit_del_16(doublepair[i+2],shft1, shft2, shft3, shft4, delmask[2]);
374     }
375     delinfo_16(shft1, shft2, shft3, shft4, delmask[3]);
376     for (int i=0; i< 32; i=i+4){
377        bit_del_16(doublepair[i+3],shft1, shft2, shft3, shft4, delmask[3]);
378     }
379
380    short u8_bytes_per_reg[8];
381
382    for (int i=0; i< 4; i++){
383      p2s_bytemerge(doublepair[i],doublepair[4+i],doublepair[8+i],doublepair[12+i],doublepair[16+i],doublepair[20+i],doublepair[24+i],doublepair[28+i],
384                        U8[i*8+7],U8[i*8+6],U8[i*8+5],U8[i*8+4],U8[i*8+3],U8[i*8+2],U8[i*8+1],U8[i*8]);
385       for(int k=0; k<8; k++) u8_bytes_per_reg[k] = 0;
386       del_count(delmask[i],u8_bytes_per_reg);
387 
388       for(int j=0; j<8; j++){
389        sisd_store_unaligned(U8[i*8+j],(SIMD_type *) (*targetbuf));
390        *targetbuf += u8_bytes_per_reg[j];
391       }
392    }
393
394    if(!error_found) (*srcbuf) += units_read;
395
396
397    PERF_SEC_END(transcode_timer, units_read*2);
398
399
400    } while ((units_read == BLOCK_SIZE) && !error_found);
401
402}
403
404
405
406
407int
408main(int argc, char * argv[]) {
409        char * infilename, * outfilename;       
410        FILE *infile, *outfile;
411        struct stat fileinfo;
412        const UChar * srcbuf;
413        const UChar * srclimit;
414        const char * targetlimit;
415        char * targetbuf;
416        char * target_head;
417        UErrorCode status;
418        int chars_read;
419
420        if (argc < 2) {
421                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
422                exit(-1);
423        }
424
425        infilename = argv[1];
426        stat(infilename, &fileinfo);
427        infile = fopen(infilename, "rb");
428        if (!infile) {
429                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
430                exit(-1);
431        }
432       
433        if (argc < 3) outfile = stdout;
434        else {
435                outfilename = argv[2];
436                outfile = fopen(outfilename, "wb");
437                if (!outfile) {
438                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
439                        exit(-1);
440                }
441        }
442
443
444        srcbuf = (UChar *) malloc(fileinfo.st_size+1);
445        if (!srcbuf) {
446              fprintf(stderr, "Error: buffer for %s of size %zu cannot be created.\n", infilename, fileinfo.st_size+1);
447              exit(-1);
448        }
449
450        PERF_SEC_INIT(transcode_timer);
451
452
453        chars_read = fread((void *)srcbuf, 1, fileinfo.st_size, infile);
454
455        srclimit = srcbuf + chars_read/2;
456//      (*srcbuf)[fileinfo.st_size] = '\0';
457        fclose(infile);
458
459        targetbuf = (char *) malloc(chars_read*2);
460        targetlimit = targetbuf + chars_read*2;
461        target_head = targetbuf;
462
463        u16u8(&targetbuf, targetlimit, &srcbuf, srclimit, &status);
464        fwrite(target_head , 1 ,  targetbuf - target_head, outfile );
465
466        if (status == U_ILLEGAL_CHAR_FOUND) {
467                fprintf(stderr, "Illegal UTF-16 sequence at position %lu in source.\n", chars_read-(srclimit-srcbuf)*2);
468        }
469        else if (status == U_TRUNCATED_CHAR_FOUND) {
470                fprintf(stderr, "EOF with incomplete UTF-16 sequence at position %lu in source.\n",chars_read-(srclimit-srcbuf)*2);
471        }
472
473        PERF_SEC_DUMP(transcode_timer);
474
475        fclose(outfile);
476
477        return(0);
478}
Note: See TracBrowser for help on using the repository browser.