File Coverage

perlsubs.c
Criterion Covered Total %
statement 185 200 92.5
branch 80 114 70.1
condition n/a
subroutine n/a
pod n/a
total 265 314 84.3


line stmt bran cond sub pod time code
1             /* Fast GF(2^m) library routines */
2             /*
3             Copyright (c) by Declan Malone 2009.
4             Licensed under the terms of the GNU General Public License and
5             the GNU Lesser (Library) General Public License.
6             */
7              
8              
9 1607           SV* mat_alloc_c(char* class, int rows, int cols, int width, int org) {
10              
11             gf2_matrix_t* Matrix;
12             SV* obj_ref;
13             SV* obj;
14            
15 1607           Matrix=malloc(sizeof (gf2_matrix_t));
16              
17 1607 50         if (Matrix == NULL) return &PL_sv_undef;
18              
19 1607           Matrix->values=malloc(rows * cols * width);
20 1607 50         if (Matrix->values == NULL) { free(Matrix); return NULL; }
21 1607           memset(Matrix->values,0,rows * cols * width);
22              
23 1607           Matrix->alloc_bits = FREE_BOTH;
24 1607           Matrix->rows = rows;
25 1607           Matrix->cols = cols;
26 1607           Matrix->width = width;
27 1607           Matrix->organisation = org;
28            
29 1607           obj_ref = newSViv(0);
30 1607           obj = newSVrv(obj_ref, class);
31              
32 1607           sv_setiv(obj,(IV)Matrix);
33 1607           SvREADONLY_on(obj);
34 1607           return obj_ref;
35             }
36              
37 1607           void mat_DESTROY (SV* Self) {
38 1607 50         gf2_matrix_t *m=(gf2_matrix_t*)SvIV(SvRV(Self));
39 1607 50         if (m->alloc_bits & 1)
40 1607           free(m->values);
41 1607 50         if (m->alloc_bits & 2)
42 1607           free(m);
43 1607           }
44              
45             /* accessor methods; get info on ROWS, COLS, etc. */
46 4136           int mat_ROWS (SV* Self) {
47 4136 50         return ((gf2_matrix_t*)SvIV(SvRV(Self)))->rows;
48             }
49              
50 14793           int mat_COLS (SV* Self) {
51 14793 50         return ((gf2_matrix_t*)SvIV(SvRV(Self)))->cols;
52             }
53              
54 5272           int mat_WIDTH (SV* Self) {
55 5272 50         return ((gf2_matrix_t*)SvIV(SvRV(Self)))->width;
56             }
57              
58 2614           int mat_ORGNUM (SV* Self) {
59 2614 50         return ((gf2_matrix_t*)SvIV(SvRV(Self)))->organisation;
60             }
61              
62 41070           gf2_u32 mat_getval(SV *Self, int row, int col) {
63 41070 50         gf2_matrix_t *m=(gf2_matrix_t*)SvIV(SvRV(Self));
64 41070           int down=gf2_matrix_offset_down(m);
65 41070           int right=gf2_matrix_offset_right(m);
66 41070           void *p=(void*)m->values + (row * down) + (col * right);
67              
68             gf2_u8 u8;
69             gf2_u16 u16;
70             gf2_u32 u32;
71              
72 41070 50         if ((row < 0) || (row >= m->rows)) {
    50          
73 0           fprintf (stderr, "Math::FastGF2::Matrix - row out of range in getval\n");
74 0           return 0;
75             }
76 41070 50         if ((col < 0) || (col >= m->cols)) {
    50          
77 0           fprintf (stderr, "Math::FastGF2::Matrix - col out of range in getval\n");
78 0           return 0;
79             }
80              
81 41070           switch (m->width) {
82             case 1:
83 36096           u8=*((gf2_u8*)p);
84 36096           return u8;
85             case 2:
86 2548           u16=*((gf2_u16*)p);
87 2548           return u16;
88             case 4:
89 2426           u32=*((gf2_u32*)p);
90 2426           return u32;
91             default:
92 0           fprintf(stderr,"Unsupported width %d in getval\n",m->width);
93 0           return 0;
94             }
95             }
96              
97 30436           gf2_u32 mat_setval(SV *Self, int row, int col, gf2_u32 val) {
98 30436 50         gf2_matrix_t *m=(gf2_matrix_t*)SvIV(SvRV(Self));
99 30436           int down=gf2_matrix_offset_down(m);
100 30436           int right=gf2_matrix_offset_right(m);
101 30436           void *p=(void*)m->values + (row * down) + (col * right);
102              
103             gf2_u8 u8;
104             gf2_u16 u16;
105             gf2_u32 u32;
106              
107 30436 50         if ((row < 0) || (row >= m->rows)) {
    50          
108 0           fprintf (stderr, "Math::FastGF2::Matrix - row out of range in setval\n");
109 0           return;
110             }
111              
112 30436 50         if ((col < 0) || (col >= m->cols)) {
    50          
113 0           fprintf (stderr, "Math::FastGF2::Matrix - col out of range in setval\n");
114 0           return;
115             }
116              
117 30436           switch (m->width) {
118             case 1:
119 26716           *((gf2_u8*)p)=(gf2_u8)val;
120 26716           break;
121             case 2:
122 1918           *((gf2_u16*)p)=(gf2_u16)val;
123 1918           break;
124             case 4:
125 1802           *((gf2_u32*)p)=(gf2_u32)val;
126 1802           break;
127             default:
128 0           fprintf(stderr,"Unsupported width %d in setval\n",m->width);
129 0           break;
130             }
131 30436           return val;
132             }
133              
134 4454           static int mat_local_byte_order (void) {
135 4454           gf2_u16 test=0x0201;
136 4454           char* first=(char*)&test;
137              
138 4454           return (int) *first;
139             }
140              
141             /*
142             This should only be called from the Perl module code, so no checking
143             on args is done. Self, Transform and Result are expected to have
144             been already initialised and other values are expected to be sane.
145             */
146             void
147 14           mat_multiply_submatrix_c (SV *Self, SV *Transform, SV *Result,
148             int self_row, int result_row, int nrows,
149             int xform_col, int result_col, int ncols) {
150 14 50         gf2_matrix_t *self = (gf2_matrix_t*) SvIV(SvRV(Self));
151 14 50         gf2_matrix_t *xform = (gf2_matrix_t*) SvIV(SvRV(Transform));
152 14 50         gf2_matrix_t *result = (gf2_matrix_t*) SvIV(SvRV(Result));
153            
154             /* i == input == self, t == transform, o == output == result; r <- i * t */
155             /* all offsets are measured in bytes */
156 14           int idown = gf2_matrix_offset_down(self);
157 14           int iright = gf2_matrix_offset_right(self);
158 14           int tdown = gf2_matrix_offset_down(xform);
159 14           int tright = gf2_matrix_offset_right(xform);
160 14           int odown = gf2_matrix_offset_down(result);
161 14           int oright = gf2_matrix_offset_right(result);
162              
163             gf2_u8 u8, *u8_irp, *u8_orp, *u8_tcp, *u8_ocp, *u8_vip, *u8_vtp;
164             gf2_u16 u16, *u16_irp, *u16_orp, *u16_tcp, *u16_ocp, *u16_vip, *u16_vtp;
165             gf2_u32 u32, *u32_irp, *u32_orp, *u32_tcp, *u32_ocp, *u32_vip, *u32_vtp;
166              
167             int r,c,v;
168              
169 14           switch (self->width) {
170             case 1:
171 18 100         for (r=0,
172 2           u8_irp=self->values + idown * self_row,
173 2           u8_orp=result->values + odown * result_row;
174             r < nrows;
175 16           ++r, u8_irp += idown, u8_orp + odown) {
176 144 100         for (c=0,
177 16           u8_tcp=xform->values + tright * xform_col,
178 16           u8_ocp=result->values + oright * result_col;
179             c < ncols;
180 128           ++c, u8_tcp += tright, u8_ocp += oright) {
181 1024 100         for (v=0,
182 128           u8_vip=u8_irp, u8_vtp=u8_tcp,
183 128           u8=gf2_mul8(*u8_vip,*u8_vtp);
184 1024           u8_vip += iright, u8_vtp += tdown,
185 1024           ++v < self->cols; ) {
186 896           u8^=gf2_mul8(*u8_vip,*u8_vtp);
187             }
188 128           *(u8_ocp + r * odown) = u8;
189             }
190             }
191 2           break;
192              
193             /*
194             For 16- and 32-bit words, we have to divide offset values by
195             width whenever adding them to gf2_u16 or gf2_u32 pointers since
196             C increments them to point to the next word rather than the
197             next byte. Other than that (and passing the correct width
198             parameter to gf2_mul) there's no difference between the u8 and
199             u16/u32 multiplication code
200             */
201              
202             case 2:
203 34 100         for (r=0,
204 6           u16_irp=(gf2_u16 *) (self->values + idown * self_row),
205 6           u16_orp=(gf2_u16 *) (result->values + odown * result_row);
206             r < nrows;
207 28           ++r, u16_irp +=(idown >> 1), u16_orp + (odown >> 1)) {
208 172 100         for (c=0,
209 28           u16_tcp=(gf2_u16 *) (xform->values + tright * xform_col),
210 28           u16_ocp=(gf2_u16 *) (result->values + oright * result_col);
211             c < ncols;
212 144           ++c, u16_tcp += (tright >> 1), u16_ocp += (oright >> 1)) {
213 832 100         for (v=0,
214 144           u16_vip=u16_irp, u16_vtp=u16_tcp,
215 144           u16=gf2_mul(16,*u16_vip,*u16_vtp);
216 832           u16_vip += (iright >> 1), u16_vtp += (tdown >> 1),
217 832           ++v < self->cols; ) {
218 688           u16^=gf2_mul(16,*u16_vip,*u16_vtp);
219             }
220 144           *(u16_ocp + r * (odown >> 1)) = u16;
221             }
222             }
223 6           break;
224            
225             case 4:
226 34 100         for (r=0,
227 6           u32_irp=(gf2_u32 *) (self->values + idown * self_row),
228 6           u32_orp=(gf2_u32 *) (result->values + odown * result_row);
229             r < nrows;
230 28           ++r, u32_irp +=(idown >> 2), u32_orp + (odown >> 2)) {
231 172 100         for (c=0,
232 28           u32_tcp=(gf2_u32 *) (xform->values + tright * xform_col),
233 28           u32_ocp=(gf2_u32 *) (result->values + oright * result_col);
234             c < ncols;
235 144           ++c, u32_tcp += (tright >> 2), u32_ocp += (oright >> 2)) {
236 832 100         for (v=0,
237 144           u32_vip=u32_irp, u32_vtp=u32_tcp,
238 144           u32=gf2_mul(32,*u32_vip,*u32_vtp);
239 832           u32_vip += (iright >> 2), u32_vtp += (tdown >> 2),
240 832           ++v < self->cols; ) {
241 688           u32^=gf2_mul(32,*u32_vip,*u32_vtp);
242             }
243 144           *(u32_ocp + r * (odown >> 2)) = u32;
244             }
245             }
246 6           break;
247            
248             default:
249 0           fprintf(stderr,
250             "Unsupported width %d in multiply_submatrix_c\n",self->width);
251             }
252 14           }
253              
254              
255             /* No error checking, so don't call directly */
256 470           int mat_values_eq_c (SV *This, SV *That) {
257 470 50         gf2_matrix_t *this = (gf2_matrix_t*) SvIV(SvRV(This));
258 470 50         gf2_matrix_t *that = (gf2_matrix_t*) SvIV(SvRV(That));
259              
260             int thisdown, thisright;
261             int thatdown, thatright;
262             int i,j;
263              
264 470           char *thisp=this->values;
265 470           char *thatp=that->values;
266              
267 470 100         if (this->organisation == that->organisation) {
268             /* compare the quick/easy way */
269 5576 100         for (i=this->rows * this->cols * this->width;
270 5576           i--;
271 5111           ++thisp, ++thatp) {
272 5321 100         if (*thisp != *thatp) return 0;
273             }
274             } else {
275             /* compare the slow/hard way */
276 5           thisdown = gf2_matrix_offset_down(this);
277 5           thisright = gf2_matrix_offset_right(this);
278 5           thatdown = gf2_matrix_offset_down(that);
279 5           thatright = gf2_matrix_offset_right(that);
280 22 100         for (i=0;
281 22           i < this-> rows;
282 17           ++i,
283 17           thisp=this->values + i * thisdown,
284 17           thatp=that->values + i * thatdown) {
285 85 100         for (j=0;
286 85           j < this-> cols;
287 67           ++j,
288 67           thisp+=thisright - this->width,
289 67           thatp+=thatright - that->width) {
290 68           switch (this -> width) {
291             case 4:
292 0 0         if (*thisp++ != *thatp++) return 0;
293 0 0         if (*thisp++ != *thatp++) return 0;
294             case 2:
295 60 50         if (*thisp++ != *thatp++) return 0;
296             case 1:
297 68 100         if (*thisp++ != *thatp++) return 0;
298             }
299             }
300             }
301             }
302 259           return 1; /* 1 == equal */
303             }
304              
305 2226           SV* mat_get_raw_values_c (SV *Self, int row, int col,
306             int words, int byteorder) {
307 2226 50         gf2_matrix_t *self = (gf2_matrix_t*) SvIV(SvRV(Self));
308 4452           char *from_start = self->values +
309 2226           gf2_matrix_offset_down(self) * row +
310 2226           gf2_matrix_offset_right(self) * col;
311             char *to_start;
312 2226           int len=self->width * words;
313 2226           SV *Str=newSVpv(from_start, len);
314 2226           int native_byteorder=mat_local_byte_order();
315             char *from, *to;
316             int i,j;
317 2226           int width=self->width;
318              
319 2226 100         if ( (width > 1) && byteorder &&
    100          
    100          
320             (native_byteorder != byteorder) ) {
321              
322 5 50         to_start=SvPV(Str,len) + width - 1;
323 19 100         for (i=width ; i-- ; --to_start, ++from_start) {
324 14           from=from_start; to=to_start;
325 32 100         for (j=words; j--; to += width, from += width) {
326 18           *to=*from;
327             }
328             ;
329             }
330             }
331             /* sv_2mortal(Str); */ /* apparently newSVpv takes care of this */
332 2226           return Str;
333             }
334              
335 2228           void mat_set_raw_values_c (SV *Self, int row, int col,
336             int words, int byteorder,
337             SV *Str) {
338              
339 2228 50         gf2_matrix_t *self = (gf2_matrix_t*) SvIV(SvRV(Self));
340 2228           int len=self->width * words;
341             char *from_start;
342 4456           char *to_start= self->values +
343 2228           gf2_matrix_offset_down(self) * row +
344 2228           gf2_matrix_offset_right(self) * col;
345 2228           int native_byteorder=mat_local_byte_order();
346             char *from, *to;
347             int i,j;
348 2228           int width=self->width;
349              
350 2234 100         if ( (width > 1) && byteorder &&
    100          
    100          
351             (native_byteorder != byteorder) ) {
352 6 50         from_start=SvPV(Str,len) + width - 1;
353 22 100         for (i=width ; i-- ; --from_start, ++to_start) {
354 16           from=from_start; to=to_start;
355 40 100         for (j=words; j--; to += width, from += width) {
356 24           *to=*from;
357             }
358             }
359             } else {
360 2222 50         from_start=SvPV(Str,len);
361 2222           memcpy(to_start, from_start, len);
362             }
363 2228           return;
364             }
365              
366             /* new code to implement previous offset_to_rowcol */