source: proto/u8u16/template.c @ 1814

Last change on this file since 1814 was 1473, checked in by ksherdy, 8 years ago

Centralized typedefs.

File size: 11.7 KB
RevLine 
[606]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#define minimum(x,y) ((x) <(y) ?(x) :(y) )
9#include <iostream>
10using namespace std;
11
12#include "../lib/lib_simd.h"
13#include "../lib/block_carry.h"
14#include "../lib/perflib/perfsec.h"
[616]15#include "../lib/s2p.h"
16#include "../lib/p2s.h"
[606]17
18// Profiling
19#if (defined(BUFFER_PROFILING) || defined(CODE_CLOCKER))
20  #include "../lib/perflib/perfsec.h"
21#endif
22
23#ifdef BUFFER_PROFILING
24BOM_Table * transcode_timer;
25#endif
26
27#ifdef CODE_CLOCKER
28        #define NUM_EVENTS 1
29        int Events[NUM_EVENTS] = {PAPI_TOT_CYC};
30        //int Events[NUM_EVENTS] = {PAPI_L2_DCM};
31        //int Events[NUM_EVENTS] = {PAPI_TOT_CYC, PAPI_BR_MSP};
32        int cal_size = 20;
33        CC * transcode_timer = new CC(Events,NUM_EVENTS,cal_size);
34#endif
35
36/*===========================================================================*/
37/* UErrorCode */
38/* Extracted from ICU */
39/*===========================================================================*/
40
41typedef enum UErrorCode {
42
43    U_ZERO_ERROR              =  0,     /**< No error, no warning. */
44    U_TRUNCATED_CHAR_FOUND    = 11,     /**< Character conversion: Incomplete input sequence. */
45    U_ILLEGAL_CHAR_FOUND      = 12,     /**< Character conversion: Illegal input sequence/combination of input units. */
46} UErrorCode;
47
48typedef  uint16_t UChar;
49
50
51#define do_right8_shifts(vec, rshift1, rshift2, rshift4) \
52{ BitBlock s2; \
53  vec = simd_sub_8(vec, simd_srli_16(simd_and(rshift1, vec), 1)); \
54  s2 = simd_and(rshift2, vec);\
55  vec = simd_or(simd_srli_16(s2, 2), simd_xor(vec, s2));\
56  s2 = simd_and(rshift4, vec);\
57  vec = simd_or(simd_srli_16(s2, 4), simd_xor(vec, s2));\
58}
59
60static inline void del_info_8(BitBlock &del8_rshift1, BitBlock &del8_rshift2, BitBlock &del8_rshift4, BitBlock delmask){
61        BitBlock del8_trans2;
62        BitBlock del8_trans4;
63        BitBlock shift_bits;
64       
65        del8_rshift1 = simd_xor(simd_slli_8(delmask, 1), simd_slli_8(delmask, 2));
66        del8_rshift1 = simd_xor(del8_rshift1, simd_slli_8(del8_rshift1, 2));
67        del8_rshift1 = simd_xor(del8_rshift1, simd_slli_8(del8_rshift1, 4));
68        /* Transition to even delcount: odd delcount to left, this one deleted. */
69        del8_trans2 = simd_and(del8_rshift1, delmask);
70        /* Odd number of transition positions to left. */
71        del8_rshift2 = simd_xor(simd_slli_8(del8_trans2, 1), simd_slli_8(del8_trans2, 2));
72        del8_rshift2 = simd_xor(del8_rshift2, simd_slli_8(del8_rshift2, 2));
73        del8_rshift2 = simd_xor(del8_rshift2, simd_slli_8(del8_rshift2, 4));
74        /* Transition positions: odd |del2count| to left, this one a transition to even. */
75        del8_trans4 = simd_and(del8_rshift2, del8_trans2);
76        del8_rshift4 = simd_xor(simd_slli_8(del8_trans4, 1), simd_slli_8(del8_trans4, 2));
77        del8_rshift4 = simd_xor(del8_rshift4, simd_slli_8(del8_rshift4, 2));
78        del8_rshift4 = simd_xor(del8_rshift4, simd_slli_8(del8_rshift4, 4));
79        /* Only move bits that are not deleted. */
80        del8_rshift1 = simd_andc(del8_rshift1, delmask);
81        del8_rshift2 = simd_andc(del8_rshift2, delmask);
82        del8_rshift4 = simd_andc(del8_rshift4, delmask);
83        /* Update |del8_rshift2| to apply after |del8_rshift1|. */
84        del8_rshift2 = simd_sub_8(del8_rshift2, simd_srli_16(simd_and(del8_rshift1, del8_rshift2),1));
85        /* Update |del8_rshift4| to apply after |del8_rshift2| and |del8_rshift1|. */
86        del8_rshift4 = simd_sub_8(del8_rshift4, simd_srli_16(simd_and(del8_rshift1, del8_rshift4),1));
87        shift_bits = simd_and(del8_rshift2, del8_rshift4);
88        del8_rshift4 = simd_or(simd_srli_16(shift_bits, 4), simd_xor(del8_rshift4, shift_bits));
89}
90
91
92static inline void del_count(BitBlock delmask, unsigned char *u16_units_per_reg){
93
94        BitBlock delcounts_2;
95        BitBlock delcounts_4;
96        BitBlock delcounts_8;
97
98        delcounts_2 = simd_add_2_lh(delmask, delmask);
99        delcounts_4 = simd_add_4_lh(delcounts_2, delcounts_2);
100        delcounts_8 = simd_add_8_lh(delcounts_4, delcounts_4);
101        sisd_store_unaligned(simd_sub_8(simd_const_8(8), delcounts_8),
102                          (BytePack *) u16_units_per_reg);
103}
104
105
106#define BLOCK_SIZE 128       
107#define BUFFER_SIZE 12800   
108
109void u8u16(UChar ** targetbuf, const UChar * targetlimit, char ** srcbuf, const char * srclimit, UErrorCode * err){
110
111  @decl
112
113  SIMD_type u16l [8];
114  SIMD_type u16h [8];
115
116
117  BytePack U16s[16];
118  BytePack U16h[8];
119  BytePack U16l[8];
120
121  BitBlock EOF_mask;
122
123  BitBlock U8[8];
124
125  int pos = 0;
126
127  bool error_found = false;
128  int err_pos;
129
130  @stream_stmts
131
132       
133    while ((*srcbuf) < srclimit){
134     
135      int u8advance = minimum(srclimit-(*srcbuf),BLOCK_SIZE);
136      if(u8advance < BLOCK_SIZE){
137        EOF_mask = sisd_srl(simd_const_1(1),sisd_from_int(BLOCK_SIZE-u8advance));
138      }
139      else
140        EOF_mask = simd_const_1(1);
141     
142      BytePack * U8pack = (BytePack *) (*srcbuf);
143      U8[0] = sisd_load_unaligned(&U8pack[0]);
144      U8[1] = sisd_load_unaligned(&U8pack[1]);
145      U8[2] = sisd_load_unaligned(&U8pack[2]);
146      U8[3] = sisd_load_unaligned(&U8pack[3]);
147      U8[4] = sisd_load_unaligned(&U8pack[4]);
148      U8[5] = sisd_load_unaligned(&U8pack[5]);
149      U8[6] = sisd_load_unaligned(&U8pack[6]);
150      U8[7] = sisd_load_unaligned(&U8pack[7]); 
151     
[624]152      s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
[606]153      array_bit__0_,array_bit__1_,array_bit__2_,array_bit__3_,array_bit__4_,array_bit__5_,array_bit__6_,array_bit__7_);
154
155      array_bit__0_ &= EOF_mask;
156      array_bit__1_ &= EOF_mask;
157      array_bit__2_ &= EOF_mask;
158      array_bit__3_ &= EOF_mask;
159      array_bit__4_ &= EOF_mask;
160      array_bit__5_ &= EOF_mask;
161      array_bit__6_ &= EOF_mask;
162      array_bit__7_ &= EOF_mask;
163   
164      @block_stmts
165     
166      delmask |= ~EOF_mask;
167      error_found = bitblock_has_bit(error_mask);
168      if (error_found) {
169        int errpos = count_forward_zeroes(error_mask);
170        if (errpos >= u8advance) {
171          *err = U_TRUNCATED_CHAR_FOUND;
172        }
173        else *err = U_ILLEGAL_CHAR_FOUND;
174        BitBlock cutoff_mask = sisd_sfl(simd_const_8(-1), sisd_from_int(errpos));
175        BitBlock errbit = simd_andc(error_mask, sisd_sfli(cutoff_mask, 1));
176        u8advance = errpos;
177        if (bitblock_has_bit(simd_and(strct_u8__scope44_, errbit))) {
178          u8advance -= 3;
[648]179          /* May have already first of a surrogate pair to targetbuf. */
[705]180          if (u8advance == -3) *targetbuf -= 1;
[606]181        }
182        else if (bitblock_has_bit(simd_and(strct_u8__scope43_, errbit))) {
183          u8advance -= 2;
184        }
185        else if (bitblock_has_bit(simd_and(strct_u8__scope33_, errbit))) {
186          u8advance -= 2;
187        }
188        else if (bitblock_has_bit(simd_and(simd_or(strct_u8__scope22_, simd_or(strct_u8__scope32_, strct_u8__scope42_)), errbit))) {
189          u8advance -= 1;
190        }
[648]191        if (u8advance <= 0) {
192          (*srcbuf) += u8advance;
193          return;
194        }
[606]195        delmask |= sisd_sfl(simd_const_8(-1), sisd_from_int(u8advance));
196//      fprintf(stderr, "errpos = %i, u8advance = %i\n", errpos, u8advance);
197      }
198     
199       
200      BitBlock shift1, shift2, shift4;
201      del_info_8(shift1, shift2, shift4, delmask);
202      do_right8_shifts(array_u16lo__0_, shift1, shift2, shift4)
203      do_right8_shifts(array_u16lo__1_, shift1, shift2, shift4)
204      do_right8_shifts(array_u16lo__2_, shift1, shift2, shift4)
205      do_right8_shifts(array_u16lo__3_, shift1, shift2, shift4)
206      do_right8_shifts(array_u16lo__4_, shift1, shift2, shift4)
207      do_right8_shifts(array_u16lo__5_, shift1, shift2, shift4)
208      do_right8_shifts(array_u16lo__6_, shift1, shift2, shift4)
209      do_right8_shifts(array_u16lo__7_, shift1, shift2, shift4)
210      do_right8_shifts(array_u16hi__0_, shift1, shift2, shift4)
211      do_right8_shifts(array_u16hi__1_, shift1, shift2, shift4)
212      do_right8_shifts(array_u16hi__2_, shift1, shift2, shift4)
213      do_right8_shifts(array_u16hi__3_, shift1, shift2, shift4)
214      do_right8_shifts(array_u16hi__4_, shift1, shift2, shift4)
215      do_right8_shifts(array_u16hi__5_, shift1, shift2, shift4)
216      do_right8_shifts(array_u16hi__6_, shift1, shift2, shift4)
217      do_right8_shifts(array_u16hi__7_, shift1, shift2, shift4)
218
219      unsigned char u16_units_per_reg[16];
220     
[624]221      p2s(array_u16lo__0_,array_u16lo__1_,array_u16lo__2_,array_u16lo__3_,array_u16lo__4_,array_u16lo__5_,array_u16lo__6_,array_u16lo__7_,
222                        U16l[0], U16l[1],U16l[2] ,U16l[3] ,U16l[4] ,U16l[5] ,U16l[6] ,U16l[7]);
223      p2s(array_u16hi__0_,array_u16hi__1_,array_u16hi__2_,array_u16hi__3_,array_u16hi__4_,array_u16hi__5_,array_u16hi__6_,array_u16hi__7_,
224                        U16h[0], U16h[1],U16h[2] ,U16h[3] ,U16h[4] ,U16h[5] ,U16h[6] ,U16h[7]);
[606]225      for (int i=0; i<8; i++) {
226        U16s[2*i] = simd_mergel_8(U16l[i], U16h[i]);
227        U16s[2*i+1] = simd_mergeh_8(U16l[i], U16h[i]);
228      }
229       
230      for(int k=0; k<16; k++) u16_units_per_reg[k] = 0;
231      del_count(delmask,u16_units_per_reg);
232
233      for(int j=0; j<16; j++){
234        sisd_store_unaligned(U16s[j],(SIMD_type *) (*targetbuf));
235        *targetbuf += u16_units_per_reg[j];
236      }
[648]237
[606]238      (*srcbuf) += u8advance;
[648]239         
240      if (error_found) return;
[606]241    }
[705]242    if (test_carry(carry5)) /* scope44 pending */ {
243      *srcbuf -= 3;
244      *targetbuf -= 1;
245      *err = U_TRUNCATED_CHAR_FOUND;
246    }
247    else if (test_carry(carry_or(carry2,carry4))) {
248      /* scope33 or scope43 pending */
249      *srcbuf -= 2;
250      *err = U_TRUNCATED_CHAR_FOUND;
251    }
252    else if (test_carry(carry_or(carry0,carry_or(carry1, carry3)))) {
253      /* scope22, scope32 or scope42 pending */
254      *srcbuf -= 1;
255      *err = U_TRUNCATED_CHAR_FOUND;
256    }
257    else *err = U_ZERO_ERROR;
[606]258}
259
260
261void do_process(FILE *infile, FILE *outfile) {
262
263  int buf_pos = 0;
[646]264  int bytes_available = 0;
265  int excess_bytes, i;
[606]266  char srcbuf[BUFFER_SIZE+BLOCK_SIZE];
267  char * srclimit;
268  UChar targetbuf[BUFFER_SIZE+BLOCK_SIZE];
269  UChar * targetlimit;
270  UChar * targetbuf_start;
271  UChar * targetbuf_ptr=targetbuf;
272  char * srcbuf_ptr=srcbuf;
273  UErrorCode status;
274 
[646]275  bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
276  srclimit = srcbuf + bytes_available;
[606]277  targetbuf_start = targetbuf;
278
[646]279  while(bytes_available>0){
[606]280
281    PERF_SEC_START(transcode_timer);
282       
283    srcbuf_ptr=srcbuf;
284    targetbuf_ptr=targetbuf;
285
286    u8u16(&targetbuf_ptr, targetlimit, &srcbuf_ptr, srclimit, &status); 
[646]287    excess_bytes = (int) (srclimit - srcbuf_ptr);
288    buf_pos += bytes_available - excess_bytes;
[606]289
[646]290    PERF_SEC_END(transcode_timer, bytes_available - excess_bytes);
[606]291   
292   
293    fwrite(targetbuf_start , sizeof(UChar) ,  targetbuf_ptr - targetbuf_start, outfile );
294   
295    if (status == U_ILLEGAL_CHAR_FOUND) {
[646]296            fclose(infile);
297            fclose(outfile);
298            fprintf(stderr, "Illegal UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
[606]299            exit(-1);
300    }
301    else if (status == U_TRUNCATED_CHAR_FOUND) {
[646]302        for (i = 0; i < excess_bytes; i++) {
303          srcbuf[i] = srcbuf_ptr[i];
304        }
305        bytes_available = fread((void *) &(srcbuf[excess_bytes]), sizeof(char), BUFFER_SIZE-excess_bytes, infile);
306        if (bytes_available == 0) {
307            fclose(infile);
308            fclose(outfile);
309            fprintf(stderr, "EOF with incomplete UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
[606]310            exit(-1);
[646]311        }
312        bytes_available += excess_bytes;
313        srclimit = srcbuf + bytes_available;
[606]314    }
[646]315    else {
316      bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
317      srclimit = srcbuf + bytes_available;
318    }
[606]319  }
320}
321
322
323
324int
325main(int argc, char * argv[]) {
326        char * infilename, * outfilename;       
327        FILE *infile, *outfile;
328
329        if (argc < 2) {
330                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
331                exit(-1);
332        }
333
334        infilename = argv[1];
335        infile = fopen(infilename, "rb");
336        if (!infile) {
337                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
338                exit(-1);
339        }
340       
341        if (argc < 3) outfile = stdout;
342        else {
343                outfilename = argv[2];
344                outfile = fopen(outfilename, "wb");
345                if (!outfile) {
346                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
347                        exit(-1);
348                }
349        }
350
351
352        PERF_SEC_INIT(transcode_timer);
353
354        do_process(infile, outfile);
355       
356        PERF_SEC_DUMP(transcode_timer);
357
358        PERF_SEC_DESTROY(transcode_timer);     
359       
360        fclose(infile);
361        fclose(outfile);
362        return(0);
363}
Note: See TracBrowser for help on using the repository browser.