File Coverage

lib/Algorithm/ToNumberMunger.xs
Criterion Covered Total %
statement 20 20 100.0
branch 12 12 100.0
condition n/a
subroutine n/a
pod n/a
total 32 32 100.0


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #include
6              
7             /* 32-bit FNV-1a. uint32_t arithmetic wraps mod 2**32 for free, which is both
8             * faster and more robust than doing the masking by hand in pure Perl. The seed
9             * is folded into the offset basis so two hashed columns can be decorrelated;
10             * the pure-Perl fallback in Mungers.pm does the identical thing, so the two
11             * paths agree bit for bit. */
12              
13             MODULE = Algorithm::ToNumberMunger PACKAGE = Algorithm::ToNumberMunger
14              
15             PROTOTYPES: DISABLE
16              
17             UV
18             _fnv1a_xs(str, seed)
19             SV *str
20             UV seed
21             PREINIT:
22             STRLEN len;
23             const unsigned char *p;
24             U32 h;
25             STRLEN i;
26             CODE:
27             /* Hash the UTF-8 byte encoding of the string's characters, regardless of
28             * the scalar's internal flag. This is well-defined for any input (a wide
29             * character would make SvPVbyte croak) and matches the pure-Perl fallback,
30             * which utf8-encodes before hashing. */
31 7           p = (const unsigned char *) SvPVutf8(str, len);
32 7           h = (U32) 2166136261UL ^ (U32) seed;
33 42 100         for (i = 0; i < len; i++) {
34 35           h ^= (U32) p[i];
35 35           h *= (U32) 16777619UL;
36             }
37 7 100         RETVAL = (UV) h;
38             OUTPUT:
39             RETVAL
40              
41             NV
42             _entropy_xs(str)
43             SV *str
44             PREINIT:
45             STRLEN len;
46             const unsigned char *p;
47             STRLEN i;
48             UV counts[256];
49             NV h, n, pr, ln2;
50             CODE:
51             /* Shannon entropy (in bits) over the UTF-8 bytes of the string, matching
52             * the pure-Perl fallback's byte view. A single per-byte count pass plus a
53             * pass over the (at most 256) seen values -- the loop and the log() per
54             * distinct byte are what make this worth doing in C. */
55 12           p = (const unsigned char *) SvPVutf8(str, len);
56 12 100         if (len == 0) {
57 2           RETVAL = 0.0;
58             }
59             else {
60 10           Zero(counts, 256, UV);
61 68 100         for (i = 0; i < len; i++)
62 58           counts[p[i]]++;
63 10           n = (NV) len;
64 10           ln2 = log((NV) 2.0);
65 10           h = 0.0;
66 2570 100         for (i = 0; i < 256; i++) {
67 2560 100         if (counts[i]) {
68 49           pr = (NV) counts[i] / n;
69 49           h -= pr * (log(pr) / ln2);
70             }
71             }
72 10           RETVAL = h;
73             }
74             OUTPUT:
75             RETVAL