source: proto/u8u16/pablo_template.cpp @ 4021

Last change on this file since 4021 was 2550, checked in by ksherdy, 7 years ago

Updated project with PAPI support.

File size: 11.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <string.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7
8#define LocalCarryDeclare(name, count)\
9CarryArray<count> name;\
10
11#include "../lib/bitblock.hpp"
12#include "../lib/carryQ.hpp"
13#include "../lib/s2p.hpp"
14#include "../lib/p2s.hpp"
15
16#define minimum(x,y) ((x) <(y) ?(x) :(y) )
17#include <iostream>
18using namespace std;
19
20#include "../lib/perflib/perfsec.h"
21
22// Profiling
23#if (defined(BUFFER_PROFILING) || defined(PAPI))
24  #include "../lib/perflib/perfsec.h"
25#endif
26
27#ifdef BUFFER_PROFILING
28    BOM_Table * transcode_timer;
29#elif PAPI
30                #define PAPI_EVENTS_COUNT 2
31                int PAPI_EVENTS[PAPI_EVENTS_COUNT] = {PAPI_TOT_CYC, PAPI_BR_MSP};       
32    CC * transcode_timer;
33#else
34    void * transcode_timer;
35#endif
36
37
38/*===========================================================================*/
39/* UErrorCode */
40/* Extracted from ICU */
41/*===========================================================================*/
42
43typedef enum UErrorCode {
44
45    U_ZERO_ERROR              =  0,     /**< No error, no warning. */
46    U_TRUNCATED_CHAR_FOUND    = 11,     /**< Character conversion: Incomplete input sequence. */
47    U_ILLEGAL_CHAR_FOUND      = 12,     /**< Character conversion: Illegal input sequence/combination of input units. */
48} UErrorCode;
49
50typedef  uint16_t UChar;
51
52
53#define do_right8_shifts(vec, rshift1, rshift2, rshift4) \
54do { BitBlock s2; \
55  vec = simd<8>::sub(vec, simd<16>::srli<1>(simd_and(rshift1, vec))); \
56  s2 = simd_and(rshift2, vec);\
57  vec = simd_or(simd<16>::srli<2>(s2), simd_xor(vec, s2));\
58  s2 = simd_and(rshift4, vec);\
59  vec = simd_or(simd<16>::srli<4>(s2), simd_xor(vec, s2));\
60} while(0)
61
62static inline void del_info_8(BitBlock &del8_rshift1, BitBlock &del8_rshift2, BitBlock &del8_rshift4, BitBlock delmask){
63        BitBlock del8_trans2;
64        BitBlock del8_trans4;
65        BitBlock shift_bits;
66       
67        del8_rshift1 = simd_xor(simd<8>::slli<1>(delmask), simd<8>::slli<2>(delmask));
68        del8_rshift1 = simd_xor(del8_rshift1, simd<8>::slli<2>(del8_rshift1));
69        del8_rshift1 = simd_xor(del8_rshift1, simd<8>::slli<4>(del8_rshift1));
70        /* Transition to even delcount: odd delcount to left, this one deleted. */
71        del8_trans2 = simd_and(del8_rshift1, delmask);
72        /* Odd number of transition positions to left. */
73        del8_rshift2 = simd_xor(simd<8>::slli<1>(del8_trans2), simd<8>::slli<2>(del8_trans2));
74        del8_rshift2 = simd_xor(del8_rshift2, simd<8>::slli<2>(del8_rshift2));
75        del8_rshift2 = simd_xor(del8_rshift2, simd<8>::slli<4>(del8_rshift2));
76        /* Transition positions: odd |del2count| to left, this one a transition to even. */
77        del8_trans4 = simd_and(del8_rshift2, del8_trans2);
78        del8_rshift4 = simd_xor(simd<8>::slli<1>(del8_trans4), simd<8>::slli<2>(del8_trans4));
79        del8_rshift4 = simd_xor(del8_rshift4, simd<8>::slli<2>(del8_rshift4));
80        del8_rshift4 = simd_xor(del8_rshift4, simd<8>::slli<4>(del8_rshift4));
81        /* Only move bits that are not deleted. */
82        del8_rshift1 = simd_andc(del8_rshift1, delmask);
83        del8_rshift2 = simd_andc(del8_rshift2, delmask);
84        del8_rshift4 = simd_andc(del8_rshift4, delmask);
85        /* Update |del8_rshift2| to apply after |del8_rshift1|. */
86        del8_rshift2 = simd<8>::sub(del8_rshift2, simd<16>::srli<1>(simd_and(del8_rshift1, del8_rshift2)));
87        /* Update |del8_rshift4| to apply after |del8_rshift2| and |del8_rshift1|. */
88        del8_rshift4 = simd<8>::sub(del8_rshift4, simd<16>::srli<1>(simd_and(del8_rshift1, del8_rshift4)));
89        shift_bits = simd_and(del8_rshift2, del8_rshift4);
90        del8_rshift4 = simd_or(simd<16>::srli<2>(shift_bits), simd_xor(del8_rshift4, shift_bits));
91}
92
93
94static inline void del_count(BitBlock delmask, BitBlock & u16_units_per_reg){
95
96        BitBlock delcounts_8 = simd<8>::popcount(delmask);
97        u16_units_per_reg = simd<8>::sub(simd<8>::constant<8>(), delcounts_8);
98}
99
100
101#define BUFFER_SIZE (BLOCK_SIZE * 100)
102
103@global
104
105void u8u16(UChar ** targetbuf, const UChar * targetlimit, char ** srcbuf, const char * srclimit, UErrorCode * err){
106
107  @decl
108
109
110  BytePack U8s[8];
111  BytePack U16h[8];
112  BytePack U16l[8];
113  BytePack U16s[16];
114
115  BitBlock EOF_mask = simd<1>::constant<1>();
116
117
118  int pos = 0;
119
120  bool error_found = false;
121  int err_pos;
122
123  @stream_stmts
124
125       
126    while (((*srcbuf) < srclimit) || @any_carry ){
127     
128      int u8advance = minimum(srclimit-(*srcbuf),BLOCK_SIZE);
129
130      if(u8advance < BLOCK_SIZE){
131        EOF_mask = bitblock::srl(simd<1>::constant<1>(), convert(BLOCK_SIZE-u8advance));
132
133      }
134      else
135        EOF_mask = simd<1>::constant<1>();
136     
137      BytePack * U8pack = (BytePack *) (*srcbuf);
138      U8s[0] = bitblock::load_unaligned(&U8pack[0]);
139      U8s[1] = bitblock::load_unaligned(&U8pack[1]);
140      U8s[2] = bitblock::load_unaligned(&U8pack[2]);
141      U8s[3] = bitblock::load_unaligned(&U8pack[3]);
142      U8s[4] = bitblock::load_unaligned(&U8pack[4]);
143      U8s[5] = bitblock::load_unaligned(&U8pack[5]);
144      U8s[6] = bitblock::load_unaligned(&U8pack[6]);
145      U8s[7] = bitblock::load_unaligned(&U8pack[7]); 
146     
147      s2p(U8s[0], U8s[1], U8s[2], U8s[3], U8s[4], U8s[5], U8s[6], U8s[7],
148          u8_bits.bit_0, u8_bits.bit_1, u8_bits.bit_2, u8_bits.bit_3, u8_bits.bit_4, u8_bits.bit_5, u8_bits.bit_6, u8_bits.bit_7);
149
150        u8_bits.bit_0 = simd_and(u8_bits.bit_0, EOF_mask);
151        u8_bits.bit_1 = simd_and(u8_bits.bit_1, EOF_mask);
152        u8_bits.bit_2 = simd_and(u8_bits.bit_2, EOF_mask);
153        u8_bits.bit_3 = simd_and(u8_bits.bit_3, EOF_mask);
154        u8_bits.bit_4 = simd_and(u8_bits.bit_4, EOF_mask);
155        u8_bits.bit_5 = simd_and(u8_bits.bit_5, EOF_mask);
156        u8_bits.bit_6 = simd_and(u8_bits.bit_6, EOF_mask);
157        u8_bits.bit_7 = simd_and(u8_bits.bit_7, EOF_mask);
158   
159      @block_stmts
160     
161      u8.delmask |= ~EOF_mask;
162      error_found = bitblock::any(u8.error);
163      if (error_found) {
164        int errpos = count_forward_zeroes(u8.error);
165        if (errpos >= u8advance) {
166          *err = U_TRUNCATED_CHAR_FOUND;
167        }
168        else *err = U_ILLEGAL_CHAR_FOUND;
169        BitBlock cutoff_mask = bitblock::sll(simd<1>::constant<1>(), convert(errpos));
170        BitBlock errbit = simd_andc(u8.error, bitblock::slli<1>(cutoff_mask));
171        u8advance = errpos;
172        if (bitblock::any(simd_and(u8.scope44, errbit))) {
173          u8advance -= 3;
174          /* May have already first of a surrogate pair to targetbuf. */
175          if (u8advance == -3) *targetbuf -= 1;
176        }
177        else if (bitblock::any(simd_and(u8.scope43, errbit))) {
178          u8advance -= 2;
179        }
180        else if (bitblock::any(simd_and(u8.scope33, errbit))) {
181          u8advance -= 2;
182        }
183        else if (bitblock::any(simd_and(simd_or(u8.scope22, simd_or(u8.scope32, u8.scope42)), errbit))) {
184          u8advance -= 1;
185        }
186        if (u8advance <= 0) {
187          (*srcbuf) += u8advance;
188          return;
189        }
190        u8.delmask |= bitblock::sll(simd<1>::constant<1>(), convert(u8advance));
191//      fprintf(stderr, "errpos = %i, u8advance = %i\n", errpos, u8advance);
192      }
193     
194       
195      if (bitblock::any(u8.delmask)) {
196              BitBlock shift1, shift2, shift4;
197              del_info_8(shift1, shift2, shift4, u8.delmask);
198              do_right8_shifts(u16lo.bit_0, shift1, shift2, shift4);
199              do_right8_shifts(u16lo.bit_1, shift1, shift2, shift4);
200              do_right8_shifts(u16lo.bit_2, shift1, shift2, shift4);
201              do_right8_shifts(u16lo.bit_3, shift1, shift2, shift4);
202              do_right8_shifts(u16lo.bit_4, shift1, shift2, shift4);
203              do_right8_shifts(u16lo.bit_5, shift1, shift2, shift4);
204              do_right8_shifts(u16lo.bit_6, shift1, shift2, shift4);
205              do_right8_shifts(u16lo.bit_7, shift1, shift2, shift4);
206              if (bitblock::any(u8.scope33 | u8.surrogate)) {
207                      do_right8_shifts(u16hi.bit_0, shift1, shift2, shift4);
208                      do_right8_shifts(u16hi.bit_1, shift1, shift2, shift4);
209                      do_right8_shifts(u16hi.bit_2, shift1, shift2, shift4);
210                      do_right8_shifts(u16hi.bit_3, shift1, shift2, shift4);
211                      do_right8_shifts(u16hi.bit_4, shift1, shift2, shift4);
212              }
213              do_right8_shifts(u16hi.bit_5, shift1, shift2, shift4);
214              do_right8_shifts(u16hi.bit_6, shift1, shift2, shift4);
215              do_right8_shifts(u16hi.bit_7, shift1, shift2, shift4);
216      }
217
218      union {BitBlock i128; uint8_t i8[16];} u16_units_per_reg;
219     
220      p2s(u16lo.bit_0,u16lo.bit_1,u16lo.bit_2,u16lo.bit_3,u16lo.bit_4,u16lo.bit_5,u16lo.bit_6,u16lo.bit_7,
221                        U16l[0], U16l[1],U16l[2] ,U16l[3] ,U16l[4] ,U16l[5] ,U16l[6] ,U16l[7]);
222      p2s(u16hi.bit_0,u16hi.bit_1,u16hi.bit_2,u16hi.bit_3,u16hi.bit_4,u16hi.bit_5,u16hi.bit_6,u16hi.bit_7,
223                        U16h[0], U16h[1],U16h[2] ,U16h[3] ,U16h[4] ,U16h[5] ,U16h[6] ,U16h[7]);
224      for (int i=0; i<8; i++) {
225        U16s[2*i] = esimd<8>::mergel(U16l[i], U16h[i]);
226        U16s[2*i+1] = esimd<8>::mergeh(U16l[i], U16h[i]);
227      }
228       
229      for(int k=0; k<16; k++) u16_units_per_reg.i8[k] = 0;
230      del_count(u8.delmask,u16_units_per_reg.i128);
231
232      for(int j=0; j<16; j++){
233        bitblock::store_unaligned(U16s[j], (BitBlock *) (*targetbuf));
234        *targetbuf += u16_units_per_reg.i8[j];
235      }
236
237      (*srcbuf) += u8advance;
238         
239      if (error_found) return;
240    }
241    *err = U_ZERO_ERROR;
242}
243
244
245void do_process(FILE *infile, FILE *outfile) {
246
247  int buf_pos = 0;
248  int bytes_available = 0;
249  int excess_bytes, i;
250  char srcbuf[BUFFER_SIZE+BLOCK_SIZE];
251  char * srclimit;
252  UChar targetbuf[BUFFER_SIZE+BLOCK_SIZE];
253  UChar * targetlimit;
254  UChar * targetbuf_start;
255  UChar * targetbuf_ptr=targetbuf;
256  char * srcbuf_ptr=srcbuf;
257  UErrorCode status;
258 
259  bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
260  srclimit = srcbuf + bytes_available;
261  targetbuf_start = targetbuf;
262
263  while(bytes_available>0){
264
265    PERF_SEC_START(transcode_timer);
266       
267    srcbuf_ptr=srcbuf;
268    targetbuf_ptr=targetbuf;
269
270    u8u16(&targetbuf_ptr, targetlimit, &srcbuf_ptr, srclimit, &status); 
271    excess_bytes = (int) (srclimit - srcbuf_ptr);
272    buf_pos += bytes_available - excess_bytes;
273
274    PERF_SEC_END(transcode_timer, bytes_available - excess_bytes);
275   
276   
277    fwrite(targetbuf_start , sizeof(UChar) ,  targetbuf_ptr - targetbuf_start, outfile );
278   
279    if (status == U_ILLEGAL_CHAR_FOUND) {
280            fclose(infile);
281            fclose(outfile);
282            fprintf(stderr, "Illegal UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
283            exit(-1);
284    }
285    else if (status == U_TRUNCATED_CHAR_FOUND) {
286        for (i = 0; i < excess_bytes; i++) {
287          srcbuf[i] = srcbuf_ptr[i];
288        }
289        bytes_available = fread((void *) &(srcbuf[excess_bytes]), sizeof(char), BUFFER_SIZE-excess_bytes, infile);
290        if (bytes_available == 0) {
291            fclose(infile);
292            fclose(outfile);
293            fprintf(stderr, "EOF with incomplete UTF-8 sequence at position %lu in source.\n", (unsigned long) buf_pos);
294            exit(-1);
295        }
296        bytes_available += excess_bytes;
297        srclimit = srcbuf + bytes_available;
298    }
299    else {
300      bytes_available = fread((void *)srcbuf, sizeof(char), BUFFER_SIZE, infile);
301      srclimit = srcbuf + bytes_available;
302    }
303  }
304}
305
306
307
308int
309main(int argc, char * argv[]) {
310        char * infilename, * outfilename;       
311        FILE *infile, *outfile;
312
313        if (argc < 2) {
314                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
315                exit(-1);
316        }
317
318        infilename = argv[1];
319        infile = fopen(infilename, "rb");
320        if (!infile) {
321                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
322                exit(-1);
323        }
324       
325        if (argc < 3) outfile = stdout;
326        else {
327                outfilename = argv[2];
328                outfile = fopen(outfilename, "wb");
329                if (!outfile) {
330                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
331                        exit(-1);
332                }
333        }
334
335
336        PERF_SEC_INIT(transcode_timer);
337
338        do_process(infile, outfile);
339       
340        PERF_SEC_DUMP(transcode_timer);
341
342        PERF_SEC_DESTROY(transcode_timer);     
343       
344        fclose(infile);
345        fclose(outfile);
346        return(0);
347}
Note: See TracBrowser for help on using the repository browser.