regen/mph.pl reuse troubles

I am trying to use mph.pl for another use in Perl. mph.pl generates a=20
lookup func like this.
--------------------------------------
MPH_VALt match_uniprop( const unsigned char * const key, const U16=20
key_len ) {
     const unsigned char * ptr=3D key;
     const unsigned char * ptr_end=3D key + key_len;
     U32 h=3D MPH_SEED1;
     U32 s;
     U32 n;
     do {
         h ^=3D *ptr;
         h *=3D MPH_FNV_CONST;
     } while ( ++ptr < ptr_end );
     n=3D h % MPH_BUCKETS;
     s =3D mph_table[n].seed2;
     if (s) {
         h=3D (h >> MPH_RSHIFT) ^ s;
         n =3D h % MPH_BUCKETS;
         if (
             ( mph_table[n].pfx_len + mph_table[n].sfx_len =3D=3D key_len )=
 &&
             ( memcmp(mph_blob + mph_table[n].pfx, key,=20
mph_table[n].pfx_len) =3D=3D 0 ) &&
             ( !mph_table[n].sfx_len || memcmp(mph_blob + mph_table[n].sfx,
                 key + mph_table[n].pfx_len, mph_table[n].sfx_len) =3D=3D 0=
 )
         ) {
             return mph_table[n].value;
         }
     }
     return 0;
}
--------------------------------------
Many of my "keys" are "not found" since their "seed2" is 0, or "seed2"=20
is non-0 and is a redirect to the final correct key. How is this code=20
supposed to work?
0
bulk88
7/4/2018 2:45:16 PM
perl.perl5.porters 47434 articles. 0 followers. Follow

17 Replies
61 Views

Similar Articles

[PageSpeed] 44

On Wed, 4 Jul 2018 at 16:45, bulk 88 <bulk88@hotmail.com> wrote:
>
> I am trying to use mph.pl for another use in Perl. mph.pl generates a
> lookup func like this.
> --------------------------------------
> MPH_VALt match_uniprop( const unsigned char * const key, const U16
> key_len ) {
>      const unsigned char * ptr= key;
>      const unsigned char * ptr_end= key + key_len;
>      U32 h= MPH_SEED1;
>      U32 s;
>      U32 n;
>      do {
>          h ^= *ptr;
>          h *= MPH_FNV_CONST;
>      } while ( ++ptr < ptr_end );
>      n= h % MPH_BUCKETS;
>      s = mph_table[n].seed2;
>      if (s) {
>          h= (h >> MPH_RSHIFT) ^ s;
>          n = h % MPH_BUCKETS;
>          if (
>              ( mph_table[n].pfx_len + mph_table[n].sfx_len == key_len ) &&
>              ( memcmp(mph_blob + mph_table[n].pfx, key,
> mph_table[n].pfx_len) == 0 ) &&
>              ( !mph_table[n].sfx_len || memcmp(mph_blob + mph_table[n].sfx,
>                  key + mph_table[n].pfx_len, mph_table[n].sfx_len) == 0 )
>          ) {
>              return mph_table[n].value;
>          }
>      }
>      return 0;
> }
> --------------------------------------
> Many of my "keys" are "not found" since their "seed2" is 0, or "seed2"
> is non-0 and is a redirect to the final correct key. How is this code
> supposed to work?


This is a fairly standard (afaik) way to construct a minimal perfect hash.

The basic idea is that you have a two level structure, and effectively
hash the key twice.

The first hash finds a bucket in the array which contains a seed which
is used for the second hash, which then leads to a bucket with key
data which is compared against to determine if the key is a match.

If the first hash finds no seed, then the key cannot match.

In our case we cheat a bit, and hash the key only once, but use the
low bits for the first lookup and the high-bits for the second.

So for instance:

          h= (h >> MPH_RSHIFT) ^ s;

is how the second hash is computed. We right shift the original hash
value (by 8 bits iirc), and then xor in the seed2, which will be
non-zero.

That then gives us the bucket which contains the key data we need to
match for a valid key.

If this is not working, then there is something very dodgy in the
construction process. It would be nice to see your input key set, and
the generated tables so I could debug how this is going wrong for you.
For instance, if you are getting a seed2 of 0 for a valid key then I
would say there is some subtle difference in how the C version of the
hash function behaves and how the Perl version works and fixing that
will sort you out.

For what its worth I find this algorithm quite cool. The basic idea is
you hash all the keys, and count how many collisions there are per
bucket, you then proceed through the used buckets in descending order
of collisions, using the seed2 and the second hash function to remap
the colliding keys to unused buckets. By doing this in descending
order of collisions it means that is "easy" to deal with the high
collision buckets, (as there are lots of options), and that the "hard"
ones to place will be buckets with only one key, which can be moved
into an arbitrary position in the bucket array with the appropriate
xor.

Yves



-- 
perl -Mre=debug -e "/just|another|perl|hacker/"
0
demerphq
7/4/2018 3:13:45 PM
ZGVtZXJwaHEgd3JvdGU6DQo+IElmIHRoaXMgaXMgbm90IHdvcmtpbmcsIHRoZW4gdGhlcmUgaXMg
c29tZXRoaW5nIHZlcnkgZG9kZ3kgaW4gdGhlDQo+IGNvbnN0cnVjdGlvbiBwcm9jZXNzLiBJdCB3
b3VsZCBiZSBuaWNlIHRvIHNlZSB5b3VyIGlucHV0IGtleSBzZXQsIGFuZA0KPiB0aGUgZ2VuZXJh
dGVkIHRhYmxlcyBzbyBJIGNvdWxkIGRlYnVnIGhvdyB0aGlzIGlzIGdvaW5nIHdyb25nIGZvciB5
b3UuDQo+IEZvciBpbnN0YW5jZSwgaWYgeW91IGFyZSBnZXR0aW5nIGEgc2VlZDIgb2YgMCBmb3Ig
YSB2YWxpZCBrZXkgdGhlbiBJDQo+IHdvdWxkIHNheSB0aGVyZSBpcyBzb21lIHN1YnRsZSBkaWZm
ZXJlbmNlIGluIGhvdyB0aGUgQyB2ZXJzaW9uIG9mIHRoZQ0KPiBoYXNoIGZ1bmN0aW9uIGJlaGF2
ZXMgYW5kIGhvdyB0aGUgUGVybCB2ZXJzaW9uIHdvcmtzIGFuZCBmaXhpbmcgdGhhdA0KPiB3aWxs
IHNvcnQgeW91IG91dC4NCg0KcGVybC5vcmcgc2VydmVycyBwcm9iYWJseSBkb250IGxpa2UgdGhl
IGF0dGFjaG1lbnQgc2l6ZXMuIFNvIHJlc2VuZGluZw0KdGhpcyBhbmQgYWRkaW5nIGNvbnRlbnQu
IFRyeSAjMg0KDQpUaGVyZSBhcmUgc3RpbGwgcHJvYmxlbXMuIFRvIG1ha2Ugc3VyZSBpdHMgbm90
IG15IGNvZGUsIEkgZGlkIGEgInBlcmwNCnJlZ2VuL21rX2ludmxpc3QucGwiIHdpdGggY29tbWl0
DQpjOTEzN2ZhYjIxMTVlZTA3M2NiNmI4ODIzMmM1ODY0N2FmYzg4N2U5ICJTeW5jIHdpdGggdmVy
c2lvbi0wLjk5MjQiLg0KdW5pX2tleXdvcmRzLmggZ290IGEgaHVnZSBkZWx0YSBvbiBXaW4zMiBh
bmQgV2luNjQgYmV0d2VlbiB0aGUNCnVuaV9rZXl3b3Jkcy5oIGZpbGUgYnVuZGxlZCBpbiBibGVh
ZC4gQWxzbyB0aGUgZGVsdGFzIGluIHRoZSBXaW4zMiBhbmQNCldpbjY0IHJ1bnMgYXJlIGRpZmZl
cmVudCBiZXR3ZWVuIGVhY2ggb3RoZXIuIFNvIGl0IGlzIHNvbWV0aGluZyB0byBkbw0Kd2l0aCBX
aW5kb3dzIHNwZWNpZmljIChDUkxGPz8/IChtcGgtaXNoIGJ1ZyksIC9saWIvdW5pY29yZS8qLiog
YWthDQpta3RhYmxlcyBmaWxlcyBhcmUgZGlmZmVyZW50IG9uIFdpbmRvd3MgdnMgVW5peD8/Pz8g
KHVuaWNvZGUgYnVnKSksIGFuZA0Kc3RpbGwgc29tZXRoaW5nIHRvIGRvIHdpdGggMzIgdnMgNjQs
IG9yIGJvdGguIEV2ZW4gdGhvdWdoIFdpbjY0IHBlcmwgZGlkDQpodWdlIGRlbHRhIHRvIHVuaV9r
ZXl3b3Jkcy5oIGl0IHBhc3NlZCBtb3N0IG9mIGl0cyB0ZXN0cyBhbmQgSSBkaWRudCBzZWUNCmFu
eSB1bmljb2RlIHJlbGF0ZWQgb25lcyBhcyBJIHNhdyBpbiBXaW4zMiBwZXJsLiBXaW4zMiBwZXJs
IHdpdGggYQ0KcmVnZW5lZCB1bmlfa2V5d29yZHMuaCBmYWlsZWQgYSBtYXNzaXZlIGFtb3VudCBv
ZiB1bmljb2RlIHRlc3RzLCBzbw0KZ2VuZXJhdGluZyB1bmlfa2V5d29yZHMuaCBvbiAzMiBiaXQg
cGVybCBpcyBzdGlsbCBjb3JydXB0Lg0KDQpXaW4zMiByZWdlbmVkIHBlcmwgdGVzdCBmYWlsdXJl
cy4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NClRlc3QgU3VtbWFyeSBS
ZXBvcnQNCi0tLS0tLS0tLS0tLS0tLS0tLS0NCnJlL3VuaXByb3BzMDIudCAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFdzdGF0Og0KNjUyODAgVA0KZXN0
czogMzM1MDggRmFpbGVkOiAxMjY0KQ0KICAgIEZhaWxlZCB0ZXN0czogIDIyMjQxLTIyMjQ4LCAy
MjI5MS0yMjI5OCwgMjIzNDEtMjIzNDgsIDIyMzkxLTIyMzk4DQogICAgICAgICAgICAgICAgICAy
MjU4NS0yMjU5MiwgMjI2ODUtMjI2OTIsIDIyNzg1LTIyNzkyLCAyMjkyOS0yMjkzNg0KICAgICAg
ICAgICAgICAgICAgMjMwNzMtMjMwODAsIDIzMjE3LTIzMjI0LCAyMzY4OS0yMzY5NiwgMjM3ODkt
MjM3OTYNCiAgICAgICAgICAgICAgICAgIDIzODg5LTIzODk2LCAyNDAwNS0yNDAxMiwgMjQxMjEt
MjQxMjgsIDI0MjQ5LTI0MjU2DQogICAgICAgICAgICAgICAgICAyNDM3Ny0yNDM4NCwgMjQ0OTct
MjQ1MDQsIDI0NjE3LTI0NjI0LCAyNDY4NS0yNDY5Mg0KICAgICAgICAgICAgICAgICAgMjQ3NTMt
MjQ3NjAsIDI0ODIxLTI0ODI4LCAyNDg4OS0yNDg5NiwgMjQ5ODktMjQ5OTYNCiAgICAgICAgICAg
ICAgICAgIDI1MDg5LTI1MDk2LCAyNTIxMy0yNTIyMCwgMjUzMzctMjUzNDQsIDI1NDYxLTI1NDY4
DQogICAgICAgICAgICAgICAgICAyNTU4NS0yNTU5MiwgMjU3MDktMjU3MTYsIDI1ODMzLTI1ODQw
LCAyNTk1Ny0yNTk2NA0KICAgICAgICAgICAgICAgICAgMjYwODEtMjYwODgsIDI2MTE3LTI2MTI0
LCAyNjM4Ny0yNjM5NCwgMjY0MjMtMjY0MzANCiAgICAgICAgICAgICAgICAgIDI2NDU5LTI2NDY2
LCAyNjQ5NS0yNjUwMiwgMjY1MzEtMjY1MzgsIDI2NTY3LTI2NTc0DQogICAgICAgICAgICAgICAg
ICAyNjU4NS0yNjU5MiwgMjY2MjEtMjY2MjgsIDI2NjU3LTI2NjY0LCAyNjY3NS0yNjY4Mg0KICAg
ICAgICAgICAgICAgICAgMjY2OTMtMjY3MDAsIDI2NzExLTI2NzE4LCAyNjcyOS0yNjczNiwgMjY3
NjUtMjY3NzINCiAgICAgICAgICAgICAgICAgIDI2ODY1LTI2ODcyLCAyNjk5My0yNzAwMCwgMjcy
NTctMjcyNjQsIDI3MjkzLTI3MzAwDQogICAgICAgICAgICAgICAgICAyNzMyOS0yNzMzNiwgMjcz
NjUtMjczNzIsIDI3NDUxLTI3NDU4LCAyNzU1MS0yNzU1OA0KICAgICAgICAgICAgICAgICAgMjc2
MDEtMjc2MDgsIDI3NjM3LTI3NjQ0LCAyNzY3My0yNzY4MCwgMjc3MDktMjc3MTYNCiAgICAgICAg
ICAgICAgICAgIDI3Nzk1LTI3ODAyLCAyNzg5NS0yNzkwMiwgMjc5NDUtMjc5NTIsIDI3OTgxLTI3
OTg4DQogICAgICAgICAgICAgICAgICAyODAxNy0yODAyNCwgMjgwNTMtMjgwNjAsIDI4Mjg5LTI4
Mjk2LCAyODMyNS0yODMzMg0KICAgICAgICAgICAgICAgICAgMjg1NjktMjg1NzYsIDI4Njk3LTI4
NzA0LCAyODgxMS0yODgxOCwgMjg5MTEtMjg5MTgNCiAgICAgICAgICAgICAgICAgIDI4OTYxLTI4
OTY4LCAyODk5Ny0yOTAwNCwgMjkwMzMtMjkwNDAsIDI5MDY5LTI5MDc2DQogICAgICAgICAgICAg
ICAgICAyOTEwNS0yOTExMiwgMjkxNDEtMjkxNDgsIDI5MTc3LTI5MTg0LCAyOTIxMy0yOTIyMA0K
ICAgICAgICAgICAgICAgICAgMjkyNDktMjkyNTYsIDI5Mjg1LTI5MjkyLCAyOTMyMS0yOTMyOCwg
MjkzNTctMjkzNjQNCiAgICAgICAgICAgICAgICAgIDI5NDExLTI5NDE4LCAyOTQ0Ny0yOTQ1NCwg
Mjk0NjUtMjk0NzIsIDI5NTAxLTI5NTA4DQogICAgICAgICAgICAgICAgICAyOTUzNy0yOTU0NCwg
Mjk1NzMtMjk1ODAsIDI5NjA5LTI5NjE2LCAyOTY0NS0yOTY1Mg0KICAgICAgICAgICAgICAgICAg
Mjk2ODEtMjk2ODgsIDI5NzE3LTI5NzI0LCAyOTc1My0yOTc2MCwgMjk3ODktMjk3OTYNCiAgICAg
ICAgICAgICAgICAgIDI5ODI1LTI5ODMyLCAyOTg2MS0yOTg2OCwgMjk4OTctMjk5MDQsIDI5OTMz
LTI5OTQwDQogICAgICAgICAgICAgICAgICAyOTk2OS0yOTk3NiwgMzAwMDUtMzAwMTIsIDMwNTYx
LTMwNTY4LCAzMDY3Ny0zMDY4NA0KICAgICAgICAgICAgICAgICAgMzE0NzMtMzE0ODAsIDMxNTQ1
LTMxNTUyLCAzMTYxNy0zMTYyNCwgMzE2ODktMzE2OTYNCiAgICAgICAgICAgICAgICAgIDMxNzYx
LTMxNzY4LCAzMTc5Ny0zMTgwNCwgMzE4MzMtMzE4NDAsIDMxODUxLTMxODU4DQogICAgICAgICAg
ICAgICAgICAzMTg2OS0zMTg3NiwgMzE4ODctMzE4OTQsIDMyMDY3LTMyMDc0LCAzMjEwMy0zMjEx
MA0KICAgICAgICAgICAgICAgICAgMzIxMjEtMzIxMjgsIDMyMTU3LTMyMTY0LCAzMjE5My0zMjIw
MCwgMzIyMjktMzIyMzYNCiAgICAgICAgICAgICAgICAgIDMyMjY1LTMyMjcyLCAzMjMwMS0zMjMw
OCwgMzIzMzctMzIzNDQsIDMyMzczLTMyMzgwDQogICAgICAgICAgICAgICAgICAzMjQwOS0zMjQx
NiwgMzI0NDUtMzI0NTIsIDMyNDgxLTMyNDg4LCAzMjUxNy0zMjUyNA0KICAgICAgICAgICAgICAg
ICAgMzI1NTMtMzI1NjAsIDMyNTg5LTMyNTk2LCAzMjYyNS0zMjYzMiwgMzI2NjEtMzI2NjgNCiAg
ICAgICAgICAgICAgICAgIDMyNjk3LTMyNzA0LCAzMjczMy0zMjc0MCwgMzI4OTEtMzI4OTgsIDMy
OTkxLTMyOTk4DQogICAgICAgICAgICAgICAgICAzMzA0MS0zMzA0OCwgMzMwNTktMzMwNjYsIDMz
MDc3LTMzMDg0LCAzMzA5NS0zMzEwMg0KICAgICAgICAgICAgICAgICAgMzMxMTMtMzMxMjAsIDMz
MTMxLTMzMTM4LCAzMzE0OS0zMzE1NiwgMzMxNjctMzMxNzQNCiAgICAgICAgICAgICAgICAgIDMz
MTg1LTMzMTkyLCAzMzIyMS0zMzIyOCwgMzMyNTctMzMyNjQsIDMzMjkzLTMzMzAwDQogICAgICAg
ICAgICAgICAgICAzMzMyOS0zMzMzNiwgMzMzNDctMzMzNTQsIDMzMzY1LTMzMzcyLCAzMzM4My0z
MzM5MA0KICAgICAgICAgICAgICAgICAgMzM0MDEtMzM0MDgsIDMzNDE5LTMzNDI2LCAzMzQzNy0z
MzQ0NCwgMzM0NTUtMzM0NjINCiAgICAgICAgICAgICAgICAgIDMzNDczLTMzNDgwLCAzMzQ5MS0z
MzQ5OA0KICAgIE5vbi16ZXJvIGV4aXQgc3RhdHVzOiAyNTUNCnJlL3VuaXByb3BzMDMudCAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFdzdGF0Og0KNjUy
ODAgVA0KZXN0czogMzMzNDggRmFpbGVkOiA3OTYpDQogICAgRmFpbGVkIHRlc3RzOiAgMS04LCAx
OS0yNiwgMzctNDQsIDU1LTYyLCA3My04MCwgOTEtOTgNCiAgICAgICAgICAgICAgICAgIDEwOS0x
MTYsIDEyNy0xMzQsIDE0NS0xNTIsIDE2My0xNzAsIDE4MS0xODgNCiAgICAgICAgICAgICAgICAg
IDE5OS0yMDYsIDIxNy0yMjQsIDIzNS0yNDIsIDI1My0yNjAsIDI3MS0yNzgNCiAgICAgICAgICAg
ICAgICAgIDI4OS0yOTYsIDMwNy0zMTQsIDMyNS0zMzIsIDM0My0zNTAsIDM2MS0zNjgNCiAgICAg
ICAgICAgICAgICAgIDM3OS0zODYsIDM5Ny00MDQsIDQxNS00MjIsIDQzMy00NDAsIDQ1MS00NTgN
CiAgICAgICAgICAgICAgICAgIDQ2OS00NzYsIDQ4Ny00OTQsIDUwNS01MTIsIDUyMy01MzAsIDU0
MS01NDgNCiAgICAgICAgICAgICAgICAgIDU1OS01NjYsIDU3Ny01ODQsIDU5NS02MDIsIDY4NS02
OTIsIDc0Ny03NTQNCiAgICAgICAgICAgICAgICAgIDgwOS04MTYsIDg3MS04NzgsIDE2MjktMTYz
NiwgMTY0Ny0xNjU0DQogICAgICAgICAgICAgICAgICAxNjY1LTE2NzIsIDE2ODMtMTY5MCwgMTg0
NS0xODUyLCAxODYzLTE4NzANCiAgICAgICAgICAgICAgICAgIDE4ODEtMTg4OCwgMTg5OS0xOTA2
LCAxOTE3LTE5MjQsIDE5MzUtMTk0Mg0KICAgICAgICAgICAgICAgICAgMTk1My0xOTYwLCAxOTcx
LTE5NzgsIDIwNzktMjA4NiwgMjExNS0yMTIyDQogICAgICAgICAgICAgICAgICAyMTUxLTIxNTgs
IDIxODctMjE5NCwgMjIyMy0yMjMwLCAyMjU5LTIyNjYNCiAgICAgICAgICAgICAgICAgIDIyNzct
MjI4NCwgMjMxMy0yMzIwLCAyMzY3LTIzNzQsIDI0MDMtMjQxMA0KICAgICAgICAgICAgICAgICAg
MjQ5My0yNTAwLCAyNjE3LTI2MjQsIDI3OTEtMjc5OCwgMjg5MS0yODk4DQogICAgICAgICAgICAg
ICAgICAzMDA1LTMwMTIsIDMxMzMtMzE0MCwgMzIxNS0zMjIyLCAzMjUxLTMyNTgNCiAgICAgICAg
ICAgICAgICAgIDM0ODUtMzQ5MiwgMzUyMS0zNTI4LCAzNjI5LTM2MzYsIDM2NDctMzY1NA0KICAg
ICAgICAgICAgICAgICAgMzY2NS0zNjcyLCAzNjgzLTM2OTAsIDM3NzMtMzc4MCwgMzc5MS0zNzk4
DQogICAgICAgICAgICAgICAgICAzODA5LTM4MTYsIDM4MjctMzgzNCwgMzg0NS0zODUyLCAzODYz
LTM4NzANCiAgICAgICAgICAgICAgICAgIDM4ODEtMzg4OCwgMzg5OS0zOTA2LCA0MDYxLTQwNjgs
IDQxNjEtNDE2OA0KICAgICAgICAgICAgICAgICAgNDI2MS00MjY4LCA0Mjc5LTQyODYsIDQyOTct
NDMwNCwgNDMxNS00MzIyDQogICAgICAgICAgICAgICAgICA0MzMzLTQzNDAsIDQzNTEtNDM1OCwg
NDM2OS00Mzc2LCA0Mzg3LTQzOTQNCiAgICAgICAgICAgICAgICAgIDQ0NzctNDQ4NCwgNDQ5NS00
NTAyLCA0NTEzLTQ1MjAsIDQ1MzEtNDUzOA0KICAgICAgICAgICAgICAgICAgNDU2Ny00NTc0LCA0
NjAzLTQ2MTAsIDIwOTU1LTIwOTU4LCAyMTEwNS0yMTEwOA0KICAgICAgICAgICAgICAgICAgMjEx
MzMtMjExMzYNCiAgICBOb24temVybyBleGl0IHN0YXR1czogMjU1DQp1bmkvY2xhc3MudCAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChXc3RhdDoN
CjAgVGVzdHMNCjogMTEgRmFpbGVkOiAxKQ0KICAgIEZhaWxlZCB0ZXN0OiAgMTENCi0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KSGVyZSBodHRwczovL2dpc3QuZ2l0aHVi
LmNvbS9idWxrODgvMzI4MDYwMWQ0ZjkzNTJmODNkZGU5OGY3MGY0MGNmNzAgYXJlIA0KdGhlIDMg
ZGlmZnMgb2YgdW5pX2tleXdvcmRzLmggd2hlbiBJIHRyaWVkIHRvIHJlZ2VuIGl0LiBBbmQNCmEg
ZGlmZiBmcm9tIGEgYnJva2VuIChmYWlscyB0ZXN0cykgV2luMzIgcmVnZW4gdG8gYSBjb3JyZWN0
IChwYXNzZXMNCnRlc3RzKSBXaW42NCByZWdlbi4NCg==
0
bulk88
7/4/2018 9:55:54 PM
I dont think this is a problem with mph.pl itself. I think this is
some issue with how Karl is using it, in particular how the keyset is
including strings with engineering notation in them, and for some
reason when *you* run it, you get an extra digit that Karl did not
when he ran it. I have to admit to being surprised to finding
engineering notation in this data set.

Consider this line:

+  {    72,  9113,  6972,   3,   9, PL_NV__3_SLASH_8 }   /* nv=3.75e-001 */,

and the comparable string from Karl:

-  {     3,  9076,  7209,   3,   8, PL_NV__3_SLASH_8 }   /* nv=3.75e-01 */,

The extra 0 in your version appears to be breaking things.

Also if you look at the header comment:

 /*
 rows: 6580
 seed: 1348825708
-full length of keys: 92584
-blob length: 9199
+full length of keys: 92660
+blob length: 9236
 ref length: 52640
-data size: 61839 (%66.79)
+data size: 61876 (%66.78)
 */

the key point to look at here is the "full length of keys", somehow
when you ran the script the key set was 76 characters longer than when
Karl ran it. I assume because of this engineering notation issue. I
admit to being surprised about this, I almost wonder if something is
inappropriately evaling the source and inadvertently convering 3/8
into 3.75e-01 or 3.75e-001.

The code I wrote expects a hash as an argument, and the keys of that
hash are what it processes, so this bug is not in mph itself but in
the code that computes this initial hash.

Yves
On Wed, 4 Jul 2018 at 23:56, bulk 88 <bulk88@hotmail.com> wrote:
>
> demerphq wrote:
> > If this is not working, then there is something very dodgy in the
> > construction process. It would be nice to see your input key set, and
> > the generated tables so I could debug how this is going wrong for you.
> > For instance, if you are getting a seed2 of 0 for a valid key then I
> > would say there is some subtle difference in how the C version of the
> > hash function behaves and how the Perl version works and fixing that
> > will sort you out.
>
> perl.org servers probably dont like the attachment sizes. So resending
> this and adding content. Try #2
>
> There are still problems. To make sure its not my code, I did a "perl
> regen/mk_invlist.pl" with commit
> c9137fab2115ee073cb6b88232c58647afc887e9 "Sync with version-0.9924".
> uni_keywords.h got a huge delta on Win32 and Win64 between the
> uni_keywords.h file bundled in blead. Also the deltas in the Win32 and
> Win64 runs are different between each other. So it is something to do
> with Windows specific (CRLF??? (mph-ish bug), /lib/unicore/*.* aka
> mktables files are different on Windows vs Unix???? (unicode bug)), and
> still something to do with 32 vs 64, or both. Even though Win64 perl did
> huge delta to uni_keywords.h it passed most of its tests and I didnt see
> any unicode related ones as I saw in Win32 perl. Win32 perl with a
> regened uni_keywords.h failed a massive amount of unicode tests, so
> generating uni_keywords.h on 32 bit perl is still corrupt.
>
> Win32 regened perl test failures.
> -------------------------------------
> Test Summary Report
> -------------------
> re/uniprops02.t                                                  (Wstat:
> 65280 T
> ests: 33508 Failed: 1264)
>     Failed tests:  22241-22248, 22291-22298, 22341-22348, 22391-22398
>                   22585-22592, 22685-22692, 22785-22792, 22929-22936
>                   23073-23080, 23217-23224, 23689-23696, 23789-23796
>                   23889-23896, 24005-24012, 24121-24128, 24249-24256
>                   24377-24384, 24497-24504, 24617-24624, 24685-24692
>                   24753-24760, 24821-24828, 24889-24896, 24989-24996
>                   25089-25096, 25213-25220, 25337-25344, 25461-25468
>                   25585-25592, 25709-25716, 25833-25840, 25957-25964
>                   26081-26088, 26117-26124, 26387-26394, 26423-26430
>                   26459-26466, 26495-26502, 26531-26538, 26567-26574
>                   26585-26592, 26621-26628, 26657-26664, 26675-26682
>                   26693-26700, 26711-26718, 26729-26736, 26765-26772
>                   26865-26872, 26993-27000, 27257-27264, 27293-27300
>                   27329-27336, 27365-27372, 27451-27458, 27551-27558
>                   27601-27608, 27637-27644, 27673-27680, 27709-27716
>                   27795-27802, 27895-27902, 27945-27952, 27981-27988
>                   28017-28024, 28053-28060, 28289-28296, 28325-28332
>                   28569-28576, 28697-28704, 28811-28818, 28911-28918
>                   28961-28968, 28997-29004, 29033-29040, 29069-29076
>                   29105-29112, 29141-29148, 29177-29184, 29213-29220
>                   29249-29256, 29285-29292, 29321-29328, 29357-29364
>                   29411-29418, 29447-29454, 29465-29472, 29501-29508
>                   29537-29544, 29573-29580, 29609-29616, 29645-29652
>                   29681-29688, 29717-29724, 29753-29760, 29789-29796
>                   29825-29832, 29861-29868, 29897-29904, 29933-29940
>                   29969-29976, 30005-30012, 30561-30568, 30677-30684
>                   31473-31480, 31545-31552, 31617-31624, 31689-31696
>                   31761-31768, 31797-31804, 31833-31840, 31851-31858
>                   31869-31876, 31887-31894, 32067-32074, 32103-32110
>                   32121-32128, 32157-32164, 32193-32200, 32229-32236
>                   32265-32272, 32301-32308, 32337-32344, 32373-32380
>                   32409-32416, 32445-32452, 32481-32488, 32517-32524
>                   32553-32560, 32589-32596, 32625-32632, 32661-32668
>                   32697-32704, 32733-32740, 32891-32898, 32991-32998
>                   33041-33048, 33059-33066, 33077-33084, 33095-33102
>                   33113-33120, 33131-33138, 33149-33156, 33167-33174
>                   33185-33192, 33221-33228, 33257-33264, 33293-33300
>                   33329-33336, 33347-33354, 33365-33372, 33383-33390
>                   33401-33408, 33419-33426, 33437-33444, 33455-33462
>                   33473-33480, 33491-33498
>     Non-zero exit status: 255
> re/uniprops03.t                                                  (Wstat:
> 65280 T
> ests: 33348 Failed: 796)
>     Failed tests:  1-8, 19-26, 37-44, 55-62, 73-80, 91-98
>                   109-116, 127-134, 145-152, 163-170, 181-188
>                   199-206, 217-224, 235-242, 253-260, 271-278
>                   289-296, 307-314, 325-332, 343-350, 361-368
>                   379-386, 397-404, 415-422, 433-440, 451-458
>                   469-476, 487-494, 505-512, 523-530, 541-548
>                   559-566, 577-584, 595-602, 685-692, 747-754
>                   809-816, 871-878, 1629-1636, 1647-1654
>                   1665-1672, 1683-1690, 1845-1852, 1863-1870
>                   1881-1888, 1899-1906, 1917-1924, 1935-1942
>                   1953-1960, 1971-1978, 2079-2086, 2115-2122
>                   2151-2158, 2187-2194, 2223-2230, 2259-2266
>                   2277-2284, 2313-2320, 2367-2374, 2403-2410
>                   2493-2500, 2617-2624, 2791-2798, 2891-2898
>                   3005-3012, 3133-3140, 3215-3222, 3251-3258
>                   3485-3492, 3521-3528, 3629-3636, 3647-3654
>                   3665-3672, 3683-3690, 3773-3780, 3791-3798
>                   3809-3816, 3827-3834, 3845-3852, 3863-3870
>                   3881-3888, 3899-3906, 4061-4068, 4161-4168
>                   4261-4268, 4279-4286, 4297-4304, 4315-4322
>                   4333-4340, 4351-4358, 4369-4376, 4387-4394
>                   4477-4484, 4495-4502, 4513-4520, 4531-4538
>                   4567-4574, 4603-4610, 20955-20958, 21105-21108
>                   21133-21136
>     Non-zero exit status: 255
> uni/class.t                                                      (Wstat:
> 0 Tests
> : 11 Failed: 1)
>     Failed test:  11
> -------------------------------------
>
> Here https://gist.github.com/bulk88/3280601d4f9352f83dde98f70f40cf70 are
> the 3 diffs of uni_keywords.h when I tried to regen it. And
> a diff from a broken (fails tests) Win32 regen to a correct (passes
> tests) Win64 regen.



-- 
perl -Mre=debug -e "/just|another|perl|hacker/"
0
demerphq
7/5/2018 11:38:33 AM
On 07/05/2018 05:38 AM, demerphq wrote:
> I dont think this is a problem with mph.pl itself. 

Confirmed.  But the problem is deeper.  It stems from this:

perl.exe -le "printf \"%.*e\", 2, eval '3/8'"
3.75e-001


I think this is
> some issue with how Karl is using it, in particular how the keyset is
> including strings with engineering notation in them, and for some
> reason when *you* run it, you get an extra digit that Karl did not
> when he ran it. I have to admit to being surprised to finding
> engineering notation in this data set.
> 
> Consider this line:
> 
> +  {    72,  9113,  6972,   3,   9, PL_NV__3_SLASH_8 }   /* nv=3.75e-001 */,
> 
> and the comparable string from Karl:
> 
> -  {     3,  9076,  7209,   3,   8, PL_NV__3_SLASH_8 }   /* nv=3.75e-01 */,
> 
> The extra 0 in your version appears to be breaking things.
> 
> Also if you look at the header comment:
> 
>   /*
>   rows: 6580
>   seed: 1348825708
> -full length of keys: 92584
> -blob length: 9199
> +full length of keys: 92660
> +blob length: 9236
>   ref length: 52640
> -data size: 61839 (%66.79)
> +data size: 61876 (%66.78)
>   */
> 
> the key point to look at here is the "full length of keys", somehow
> when you ran the script the key set was 76 characters longer than when
> Karl ran it. I assume because of this engineering notation issue. I
> admit to being surprised about this, I almost wonder if something is
> inappropriately evaling the source and inadvertently convering 3/8
> into 3.75e-01 or 3.75e-001.
> 
> The code I wrote expects a hash as an argument, and the keys of that
> hash are what it processes, so this bug is not in mph itself but in
> the code that computes this initial hash.
> 
> Yves
> On Wed, 4 Jul 2018 at 23:56, bulk 88 <bulk88@hotmail.com> wrote:
>>
>> demerphq wrote:
>>> If this is not working, then there is something very dodgy in the
>>> construction process. It would be nice to see your input key set, and
>>> the generated tables so I could debug how this is going wrong for you.
>>> For instance, if you are getting a seed2 of 0 for a valid key then I
>>> would say there is some subtle difference in how the C version of the
>>> hash function behaves and how the Perl version works and fixing that
>>> will sort you out.
>>
>> perl.org servers probably dont like the attachment sizes. So resending
>> this and adding content. Try #2
>>
>> There are still problems. To make sure its not my code, I did a "perl
>> regen/mk_invlist.pl" with commit
>> c9137fab2115ee073cb6b88232c58647afc887e9 "Sync with version-0.9924".
>> uni_keywords.h got a huge delta on Win32 and Win64 between the
>> uni_keywords.h file bundled in blead. Also the deltas in the Win32 and
>> Win64 runs are different between each other. So it is something to do
>> with Windows specific (CRLF??? (mph-ish bug), /lib/unicore/*.* aka
>> mktables files are different on Windows vs Unix???? (unicode bug)), and
>> still something to do with 32 vs 64, or both. Even though Win64 perl did
>> huge delta to uni_keywords.h it passed most of its tests and I didnt see
>> any unicode related ones as I saw in Win32 perl. Win32 perl with a
>> regened uni_keywords.h failed a massive amount of unicode tests, so
>> generating uni_keywords.h on 32 bit perl is still corrupt.
>>
>> Win32 regened perl test failures.
>> -------------------------------------
>> Test Summary Report
>> -------------------
>> re/uniprops02.t                                                  (Wstat:
>> 65280 T
>> ests: 33508 Failed: 1264)
>>      Failed tests:  22241-22248, 22291-22298, 22341-22348, 22391-22398
>>                    22585-22592, 22685-22692, 22785-22792, 22929-22936
>>                    23073-23080, 23217-23224, 23689-23696, 23789-23796
>>                    23889-23896, 24005-24012, 24121-24128, 24249-24256
>>                    24377-24384, 24497-24504, 24617-24624, 24685-24692
>>                    24753-24760, 24821-24828, 24889-24896, 24989-24996
>>                    25089-25096, 25213-25220, 25337-25344, 25461-25468
>>                    25585-25592, 25709-25716, 25833-25840, 25957-25964
>>                    26081-26088, 26117-26124, 26387-26394, 26423-26430
>>                    26459-26466, 26495-26502, 26531-26538, 26567-26574
>>                    26585-26592, 26621-26628, 26657-26664, 26675-26682
>>                    26693-26700, 26711-26718, 26729-26736, 26765-26772
>>                    26865-26872, 26993-27000, 27257-27264, 27293-27300
>>                    27329-27336, 27365-27372, 27451-27458, 27551-27558
>>                    27601-27608, 27637-27644, 27673-27680, 27709-27716
>>                    27795-27802, 27895-27902, 27945-27952, 27981-27988
>>                    28017-28024, 28053-28060, 28289-28296, 28325-28332
>>                    28569-28576, 28697-28704, 28811-28818, 28911-28918
>>                    28961-28968, 28997-29004, 29033-29040, 29069-29076
>>                    29105-29112, 29141-29148, 29177-29184, 29213-29220
>>                    29249-29256, 29285-29292, 29321-29328, 29357-29364
>>                    29411-29418, 29447-29454, 29465-29472, 29501-29508
>>                    29537-29544, 29573-29580, 29609-29616, 29645-29652
>>                    29681-29688, 29717-29724, 29753-29760, 29789-29796
>>                    29825-29832, 29861-29868, 29897-29904, 29933-29940
>>                    29969-29976, 30005-30012, 30561-30568, 30677-30684
>>                    31473-31480, 31545-31552, 31617-31624, 31689-31696
>>                    31761-31768, 31797-31804, 31833-31840, 31851-31858
>>                    31869-31876, 31887-31894, 32067-32074, 32103-32110
>>                    32121-32128, 32157-32164, 32193-32200, 32229-32236
>>                    32265-32272, 32301-32308, 32337-32344, 32373-32380
>>                    32409-32416, 32445-32452, 32481-32488, 32517-32524
>>                    32553-32560, 32589-32596, 32625-32632, 32661-32668
>>                    32697-32704, 32733-32740, 32891-32898, 32991-32998
>>                    33041-33048, 33059-33066, 33077-33084, 33095-33102
>>                    33113-33120, 33131-33138, 33149-33156, 33167-33174
>>                    33185-33192, 33221-33228, 33257-33264, 33293-33300
>>                    33329-33336, 33347-33354, 33365-33372, 33383-33390
>>                    33401-33408, 33419-33426, 33437-33444, 33455-33462
>>                    33473-33480, 33491-33498
>>      Non-zero exit status: 255
>> re/uniprops03.t                                                  (Wstat:
>> 65280 T
>> ests: 33348 Failed: 796)
>>      Failed tests:  1-8, 19-26, 37-44, 55-62, 73-80, 91-98
>>                    109-116, 127-134, 145-152, 163-170, 181-188
>>                    199-206, 217-224, 235-242, 253-260, 271-278
>>                    289-296, 307-314, 325-332, 343-350, 361-368
>>                    379-386, 397-404, 415-422, 433-440, 451-458
>>                    469-476, 487-494, 505-512, 523-530, 541-548
>>                    559-566, 577-584, 595-602, 685-692, 747-754
>>                    809-816, 871-878, 1629-1636, 1647-1654
>>                    1665-1672, 1683-1690, 1845-1852, 1863-1870
>>                    1881-1888, 1899-1906, 1917-1924, 1935-1942
>>                    1953-1960, 1971-1978, 2079-2086, 2115-2122
>>                    2151-2158, 2187-2194, 2223-2230, 2259-2266
>>                    2277-2284, 2313-2320, 2367-2374, 2403-2410
>>                    2493-2500, 2617-2624, 2791-2798, 2891-2898
>>                    3005-3012, 3133-3140, 3215-3222, 3251-3258
>>                    3485-3492, 3521-3528, 3629-3636, 3647-3654
>>                    3665-3672, 3683-3690, 3773-3780, 3791-3798
>>                    3809-3816, 3827-3834, 3845-3852, 3863-3870
>>                    3881-3888, 3899-3906, 4061-4068, 4161-4168
>>                    4261-4268, 4279-4286, 4297-4304, 4315-4322
>>                    4333-4340, 4351-4358, 4369-4376, 4387-4394
>>                    4477-4484, 4495-4502, 4513-4520, 4531-4538
>>                    4567-4574, 4603-4610, 20955-20958, 21105-21108
>>                    21133-21136
>>      Non-zero exit status: 255
>> uni/class.t                                                      (Wstat:
>> 0 Tests
>> : 11 Failed: 1)
>>      Failed test:  11
>> -------------------------------------
>>
>> Here https://gist.github.com/bulk88/3280601d4f9352f83dde98f70f40cf70 are
>> the 3 diffs of uni_keywords.h when I tried to regen it. And
>> a diff from a broken (fails tests) Win32 regen to a correct (passes
>> tests) Win64 regen.
> 
> 
> 
0
khw
7/5/2018 3:50:53 PM
--_002_BN6PR04MB0963A3C460F1781D31925C67DF400BN6PR04MB0963namp_
Content-Type: text/plain; charset="utf-8"
Content-ID: <24B3C7BF24EC9C4F9B923FCF4C9537D6@namprd04.prod.outlook.com>
Content-Transfer-Encoding: base64

S2FybCBXaWxsaWFtc29uIHdyb3RlOg0KPiBPbiAwNy8wNS8yMDE4IDA1OjM4IEFNLCBkZW1lcnBo
cSB3cm90ZToNCj4+IEkgZG9udCB0aGluayB0aGlzIGlzIGEgcHJvYmxlbSB3aXRoIG1waC5wbCBp
dHNlbGYuIA0KPiANCj4gQ29uZmlybWVkLiAgQnV0IHRoZSBwcm9ibGVtIGlzIGRlZXBlci4gIEl0
IHN0ZW1zIGZyb20gdGhpczoNCj4gDQo+IHBlcmwuZXhlIC1sZSAicHJpbnRmIFwiJS4qZVwiLCAy
LCBldmFsICczLzgnIg0KPiAzLjc1ZS0wMDENCg0KTXkgYmxlYWQgV2luMzIgYW5kIFdpbjY0IFZD
MjAwOCBwZXJscyBvdXRwdXQgIjAwMSIgZm9yIHRoYXQgb25lbGluZXIsIG15IA0KY3lnd2luIHBl
cmwgNS4xNC4yIG91dHB1dHMgIjAxIi4NCg0KSSBkdW1wZWQgdGhlIFwla2V5d29yZHMgaGFzaCBw
YXNzZWQgdG8gbXBoLCBpdCBpcyBieXRld2lzZSAoJFNvcnRrZXlzPTEpIA0KaWRlbnRpY2FsIGZv
ciBXaW4zMiBhbmQgV2luNjQgcGVybCBidXQgdGhlIGdlbmVyYXRlZCBoYXNoZXMgYXJlIHN0aWxs
IA0KZGlmZmVyZW50IGJldHdlZW4gV2luMzIgYW5kIFdpbjY0LiBTbyB0aGVyZSBhcmUgMiBwcm9i
bGVtczoNCg0KXCVrZXl3b3JkcyBvbiBXaW5kb3dzIHBlcmwgaXMgbm90IHRoZSBzYW1lIGRhdGEg
c3RydWN0dXJlIGFzIG9uIFVuaXggDQpwZXJsIGJlY2F1c2Ugb2YgdGhlIHByaW50ZiB0aGluZyBh
Ym92ZS4NCg0KMzIgYml0IHBlcmwgZ2VuZXJhdGVzIGRpZmZlcmVudCBudW1iZXJzIGluIHRoZSBt
cGggaGFzaCB0aGFuIDY0IGJpdCANCnBlcmwuIEknbGwgZ3Vlc3MgbW9yZSAidXNlIGludGVnZXIi
IGlzIG5lZWRlZCBzb21ld2hlcmUgaW4gdGhlIGNvZGUuDQo=

--_002_BN6PR04MB0963A3C460F1781D31925C67DF400BN6PR04MB0963namp_
Content-Type: application/x-gzip; name="mk_invlist_keyword_dump.txt.gz"
Content-Description: mk_invlist_keyword_dump.txt.gz
Content-Disposition: attachment; filename="mk_invlist_keyword_dump.txt.gz";
	size=35504; creation-date="Thu, 05 Jul 2018 16:11:57 GMT";
	modification-date="Thu, 05 Jul 2018 16:11:57 GMT"
Content-ID: <8446FFE5E490D241A73984E1EF30A380@namprd04.prod.outlook.com>
Content-Transfer-Encoding: base64

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

--_002_BN6PR04MB0963A3C460F1781D31925C67DF400BN6PR04MB0963namp_--
0
bulk88
7/5/2018 4:11:58 PM
On 07/05/2018 09:50 AM, Karl Williamson wrote:
> On 07/05/2018 05:38 AM, demerphq wrote:
>> I dont think this is a problem with mph.pl itself. 
> 
> Confirmed.  But the problem is deeper.  It stems from this:
> 
> perl.exe -le "printf \"%.*e\", 2, eval '3/8'"
> 3.75e-001
> 

Here's some more evidence.  It looks like it could be that an extra 
leading zero is getting printed in the exponent, instead of the math 
being wrong, which in the case of a negative exponent changes the value.

perl.exe -le "printf '%.2e', .375"
3.75e-001

perl.exe -le "printf '%e', .375"
3.750000e-001

perl.exe -le "printf '%.2e', 5.5"
5.50e+000

perl.exe -le "printf '%.2e', 50.5"
5.05e+001

When I try these on linux, the exponents only contain 2 digits.
0
khw
7/5/2018 4:20:46 PM
On Thu, Jul 05, 2018 at 10:20:46AM -0600, Karl Williamson wrote:
> Here's some more evidence.  It looks like it could be that an extra leading
> zero is getting printed in the exponent, instead of the math being wrong,
> which in the case of a negative exponent changes the value.
> 
> perl.exe -le "printf '%.2e', .375"
> 3.75e-001
> 
> perl.exe -le "printf '%e', .375"
> 3.750000e-001
> 
> perl.exe -le "printf '%.2e', 5.5"
> 5.50e+000
> 
> perl.exe -le "printf '%.2e', 50.5"
> 5.05e+001
> 
> When I try these on linux, the exponents only contain 2 digits.

I haven't been following this thread closely, but note that for
floating-point formats, perl's underlying sprintf implementation -
Perl_sv_vcatpvfn_flags() - usually outsources the request to the
platform's snprintf() library function or similar.

-- 
"Strange women lying in ponds distributing swords is no basis for a system
of government. Supreme executive power derives from a mandate from the
masses, not from some farcical aquatic ceremony."
    -- Dennis, "Monty Python and the Holy Grail"
0
davem
7/5/2018 6:49:33 PM
On 07/05/2018 10:11 AM, bulk 88 wrote:
> Karl Williamson wrote:
>> On 07/05/2018 05:38 AM, demerphq wrote:
>>> I dont think this is a problem with mph.pl itself.
>>
>> Confirmed.  But the problem is deeper.  It stems from this:
>>
>> perl.exe -le "printf \"%.*e\", 2, eval '3/8'"
>> 3.75e-001
> 
> My blead Win32 and Win64 VC2008 perls output "001" for that oneliner, my
> cygwin perl 5.14.2 outputs "01".
> 
> I dumped the \%keywords hash passed to mph, it is bytewise ($Sortkeys=1)
> identical for Win32 and Win64 perl but the generated hashes are still
> different between Win32 and Win64. So there are 2 problems:
> 
> \%keywords on Windows perl is not the same data structure as on Unix
> perl because of the printf thing above.
> 
> 32 bit perl generates different numbers in the mph hash than 64 bit
> perl. I'll guess more "use integer" is needed somewhere in the code.
> 

I can confirm that a 32 bit linux build fails here.  (The printf problem 
doesn't exist on Linux.)

If I move the 'use integer' to the beginning of the program, it loops 
for as long as I've let it.

If I change that to 'use bigint', it halts, and generates the same 
uni_keywords.h as a 64 bit build does.

This indicates it is overflowing 32 bits.
0
khw
7/5/2018 9:24:08 PM
--------------CF6ABFB244094181DDB5FF20
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

On 07/05/2018 12:49 PM, Dave Mitchell wrote:
> On Thu, Jul 05, 2018 at 10:20:46AM -0600, Karl Williamson wrote:
>> Here's some more evidence.  It looks like it could be that an extra leading
>> zero is getting printed in the exponent, instead of the math being wrong,
>> which in the case of a negative exponent changes the value.
>>
>> perl.exe -le "printf '%.2e', .375"
>> 3.75e-001
>>
>> perl.exe -le "printf '%e', .375"
>> 3.750000e-001
>>
>> perl.exe -le "printf '%.2e', 5.5"
>> 5.50e+000
>>
>> perl.exe -le "printf '%.2e', 50.5"
>> 5.05e+001
>>
>> When I try these on linux, the exponents only contain 2 digits.
> 
> I haven't been following this thread closely, but note that for
> floating-point formats, perl's underlying sprintf implementation -
> Perl_sv_vcatpvfn_flags() - usually outsources the request to the
> platform's snprintf() library function or similar.

When I compile and run the attached program on the windows vm on 
dromedary, it prints
3.750000e-001

So this is a windows bug.  It's hard for me to believe though that such 
a basic bug would be undetected and unfixed.

Could someone with access to a bunch of Windows versions check this out?

--------------CF6ABFB244094181DDB5FF20
Content-Type: text/x-csrc;
 name="test.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="test.c"

#include <stdio.h>

int main(char **argv, int argc)
{

printf("%e\n", 3.0/8);
}

--------------CF6ABFB244094181DDB5FF20--
0
khw
7/7/2018 3:31:16 AM
--0000000000008fb29f05706229b9
Content-Type: text/plain; charset="UTF-8"

If, on Windows, you build Karl's test.c using (mingw) ports of gcc with:

gcc -o test.exe test.c -D__USE_MINGW_ANSI_STDIO

then the output is 3.750000e-01.
But when -D__USE_MINGW_ANSI_STDIO is not defined you get the extra '0' in
the exponent.

Perl-5.28.0 is the first version of perl where __USE_MINGW_ANSI_STDIO is
universally defined for mingw builds. In earlier versions of perl, it is
only the "long double" builds that defined __USE_MINGW_ANSI_STDIO.

So ... this windows problem should not arise with perl-5.28.0, but you can
expect to see it on all earlier versions for which nvtype is double.

I gather that the trailing zeroes in the significand are not an issue -
that the only problem is the extra digit in the exponent. Correct ?

(I've no experience what happens wrt modern perls that have been built with
MS compilers.)

Cheers,
Rob

On Sat, Jul 7, 2018 at 1:31 PM, Karl Williamson <khw@cpan.org> wrote:

> On 07/05/2018 12:49 PM, Dave Mitchell wrote:
>
>> On Thu, Jul 05, 2018 at 10:20:46AM -0600, Karl Williamson wrote:
>>
>>> Here's some more evidence.  It looks like it could be that an extra
>>> leading
>>> zero is getting printed in the exponent, instead of the math being wrong,
>>> which in the case of a negative exponent changes the value.
>>>
>>> perl.exe -le "printf '%.2e', .375"
>>> 3.75e-001
>>>
>>> perl.exe -le "printf '%e', .375"
>>> 3.750000e-001
>>>
>>> perl.exe -le "printf '%.2e', 5.5"
>>> 5.50e+000
>>>
>>> perl.exe -le "printf '%.2e', 50.5"
>>> 5.05e+001
>>>
>>> When I try these on linux, the exponents only contain 2 digits.
>>>
>>
>> I haven't been following this thread closely, but note that for
>> floating-point formats, perl's underlying sprintf implementation -
>> Perl_sv_vcatpvfn_flags() - usually outsources the request to the
>> platform's snprintf() library function or similar.
>>
>
> When I compile and run the attached program on the windows vm on
> dromedary, it prints
> 3.750000e-001
>
> So this is a windows bug.  It's hard for me to believe though that such a
> basic bug would be undetected and unfixed.
>
> Could someone with access to a bunch of Windows versions check this out?
>

--0000000000008fb29f05706229b9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>If, on Windows,=C2=A0you build Karl&#39;s test.c usin=
g (mingw) ports of gcc=C2=A0with:</div><div><br></div><div>gcc -o test.exe =
test.c -D__USE_MINGW_ANSI_STDIO</div><div><br></div><div>then the output is=
 3.750000e-01.</div><div>But when -D__USE_MINGW_ANSI_STDIO is not defined y=
ou get the extra &#39;0&#39; in the exponent.</div><div><br></div><div>Perl=
-5.28.0 is the first version of perl where __USE_MINGW_ANSI_STDIO is univer=
sally defined for mingw builds. In earlier versions of perl, it is only the=
 &quot;long double&quot; builds that defined __USE_MINGW_ANSI_STDIO.</div><=
div><br></div><div>So ... this windows=C2=A0problem should not arise with p=
erl-5.28.0, but you can expect to see it on all earlier versions for which =
nvtype is double.</div><div><br></div><div>I gather that the trailing zeroe=
s in the significand are not an issue - that the only problem is the extra =
digit in the exponent. Correct ?</div><div><br></div><div>(I&#39;ve no expe=
rience=C2=A0what happens wrt=C2=A0modern perls that have been built with MS=
 compilers.)</div><div><br></div><div>Cheers,</div><div>Rob</div></div><div=
 class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Sat, Jul 7, 2018 a=
t 1:31 PM, Karl Williamson <span dir=3D"ltr">&lt;<a href=3D"mailto:khw@cpan=
..org" target=3D"_blank">khw@cpan.org</a>&gt;</span> wrote:<br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex">On 07/05/2018 12:49 PM, Dave Mitchell wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding=
-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-l=
eft-style:solid">
On Thu, Jul 05, 2018 at 10:20:46AM -0600, Karl Williamson wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding=
-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-l=
eft-style:solid">
Here&#39;s some more evidence.=C2=A0 It looks like it could be that an extr=
a leading<br>
zero is getting printed in the exponent, instead of the math being wrong,<b=
r>
which in the case of a negative exponent changes the value.<br>
<br>
perl.exe -le &quot;printf &#39;%.2e&#39;, .375&quot;<br>
3.75e-001<br>
<br>
perl.exe -le &quot;printf &#39;%e&#39;, .375&quot;<br>
3.750000e-001<br>
<br>
perl.exe -le &quot;printf &#39;%.2e&#39;, 5.5&quot;<br>
5.50e+000<br>
<br>
perl.exe -le &quot;printf &#39;%.2e&#39;, 50.5&quot;<br>
5.05e+001<br>
<br>
When I try these on linux, the exponents only contain 2 digits.<br>
</blockquote>
<br>
I haven&#39;t been following this thread closely, but note that for<br>
floating-point formats, perl&#39;s underlying sprintf implementation -<br>
Perl_sv_vcatpvfn_flags() - usually outsources the request to the<br>
platform&#39;s snprintf() library function or similar.<br>
</blockquote>
<br>
When I compile and run the attached program on the windows vm on dromedary,=
 it prints<br>
3.750000e-001<br>
<br>
So this is a windows bug.=C2=A0 It&#39;s hard for me to believe though that=
 such a basic bug would be undetected and unfixed.<br>
<br>
Could someone with access to a bunch of Windows versions check this out?<br=
>
</blockquote></div><br></div>

--0000000000008fb29f05706229b9--
0
sisyphus359
7/7/2018 5:36:29 AM
On Fri, Jul 06, 2018 at 09:31:16PM -0600, Karl Williamson wrote:
> When I compile and run the attached program on the windows vm on dromedary,
> it prints
> 3.750000e-001
> 
> So this is a windows bug.  It's hard for me to believe though that such a
> basic bug would be undetected and unfixed.
> 
> Could someone with access to a bunch of Windows versions check this out?

> #include <stdio.h>
> 
> int main(char **argv, int argc)
> {
> 
> printf("%e\n", 3.0/8);
> }

I'm not getting why using 3 digits rather than two in the exponent is a
bug. According to the glibc man page for sprintf() and %e,

    The exponent always contains at least two digits; if the value is
    zero, the exponent is 00.

So I see there
a) the idea that leading zeros in the exponent are ok;
b) there is no guarantee that there will be only 2 digits.

-- 
"Do not dabble in paradox, Edward, it puts you in danger of fortuitous wit."
    -- Lady Croom, "Arcadia"
0
davem
7/7/2018 8:21:09 AM
On Sat, Jul 7, 2018 at 3:22 AM Dave Mitchell <davem@iabyn.com> wrote:
>
> On Fri, Jul 06, 2018 at 09:31:16PM -0600, Karl Williamson wrote:
> > When I compile and run the attached program on the windows vm on dromedary,
> > it prints
> > 3.750000e-001
> >
> > So this is a windows bug.  It's hard for me to believe though that such a
> > basic bug would be undetected and unfixed.
> >
> > Could someone with access to a bunch of Windows versions check this out?
>
> > #include <stdio.h>
> >
> > int main(char **argv, int argc)
> > {
> >
> > printf("%e\n", 3.0/8);
> > }
>
> I'm not getting why using 3 digits rather than two in the exponent is a
> bug. According to the glibc man page for sprintf() and %e,
>
>     The exponent always contains at least two digits; if the value is
>     zero, the exponent is 00.
>
> So I see there
> a) the idea that leading zeros in the exponent are ok;
> b) there is no guarantee that there will be only 2 digits.

C99, section 7.19.6.1, says regarding "e":

"The exponent always contains at least two digits, and only as many
more digits as necessary to represent the exponent. If the value is
zero, the exponent is zero."

so apparently 3 digits when two are enough is not C99-compliant, but
it still seems like a very flimsy thing to depend on, we still don't
require C99 for other reasons, and clearly not everything follows C99
in strictly regulating the number of leading zeroes in the exponent.
0
craig
7/7/2018 1:51:52 PM
On Fri, 6 Jul 2018 21:31:16 -0600
Karl Williamson <khw@cpan.org> wrote:

> When I compile and run the attached program on the windows vm on dromedary, it prints
> 3.750000e-001
> 
> So this is a windows bug.  It's hard for me to believe though that such a basic bug would be undetected and unfixed.
> 
> Could someone with access to a bunch of Windows versions check this out?

MinGW bundled with strawberry 5.26.2 (__USE_MINGW_ANSI_STDIO does *not*
change the result):

3.750000e-001

Visual C++ 2013:

3.750000e-001

Visual C++ 2015:

3.750000e-01

Visual C++ 2017:

3.750000e-01
0
me
7/7/2018 2:08:50 PM
On 07/07/2018 07:51 AM, Craig A. Berry wrote:
> On Sat, Jul 7, 2018 at 3:22 AM Dave Mitchell <davem@iabyn.com> wrote:
>>
>> On Fri, Jul 06, 2018 at 09:31:16PM -0600, Karl Williamson wrote:
>>> When I compile and run the attached program on the windows vm on dromedary,
>>> it prints
>>> 3.750000e-001
>>>
>>> So this is a windows bug.  It's hard for me to believe though that such a
>>> basic bug would be undetected and unfixed.
>>>
>>> Could someone with access to a bunch of Windows versions check this out?
>>
>>> #include <stdio.h>
>>>
>>> int main(char **argv, int argc)
>>> {
>>>
>>> printf("%e\n", 3.0/8);
>>> }
>>
>> I'm not getting why using 3 digits rather than two in the exponent is a
>> bug. According to the glibc man page for sprintf() and %e,
>>
>>      The exponent always contains at least two digits; if the value is
>>      zero, the exponent is 00.
>>
>> So I see there
>> a) the idea that leading zeros in the exponent are ok;
>> b) there is no guarantee that there will be only 2 digits.
> 
> C99, section 7.19.6.1, says regarding "e":
> 
> "The exponent always contains at least two digits, and only as many
> more digits as necessary to represent the exponent. If the value is
> zero, the exponent is zero."
> 
> so apparently 3 digits when two are enough is not C99-compliant, but
> it still seems like a very flimsy thing to depend on, we still don't
> require C99 for other reasons, and clearly not everything follows C99
> in strictly regulating the number of leading zeroes in the exponent.
> 


I was confused; there is no problem with leading zeros.  Remember that I 
work on perl for selfish reasons: I always loved programming, I like 
perl, and my doing this work appears to be slowing down the inevitable 
decline of my mental faculties, but unfortunately not stopping that 
decline altogether.

I erroneously was thinking that e-001 vs e-01 meant .0375 instead of 
..375.  But I was completely forgetting how things work.  In other words, 
I confused e-001 as being equivalent to e-02.

I do note that other people who seem to know what they're doing 
generally, also get confused sometimes, and that is reassuring.

(I had a friend who was a math prof who told me that when he went back 
to read his dissertation 20 years later, he couldn't understand it.)

In fact, changing to use bigint in regen/mph.pl on the 32 bit windows vm 
attached to dromedary, causes it to succeed in generating a header file. 
  It is different from the one I see on my 64 bit linux box, but the 
test suite succeeds when using it.

So there is no problem here with Windows.  I will patch mph.pl to use 
bigint.  This is only rarely executed, as little as once per development 
cycle once we get it into a state where we're not fiddling with it, and 
the slowdown is actually not really noticeable compared to the vast 
amount of work of going through all the Unicode property definitions and 
assembling them into a state where mph.pl can be called on their data.
0
khw
7/7/2018 3:58:10 PM
On 07/07/2018 09:58 AM, Karl Williamson wrote:
> So there is no problem here with Windows.  I will patch mph.pl to use 
> bigint.  This is only rarely executed, as little as once per development 
> cycle once we get it into a state where we're not fiddling with it, and 
> the slowdown is actually not really noticeable compared to the vast 
> amount of work of going through all the Unicode property definitions and 
> assembling them into a state where mph.pl can be called on their data.

Now done via 00d503c441212052333efea48fdca1499869a60c
I had to use bignum instead of bigint, as there is one floating 
calculation that otherwise was coming out as 0.
0
khw
7/7/2018 6:43:59 PM
--000000000000afb68c0570e27c65
Content-Type: text/plain; charset="UTF-8"

On Thu, 5 Jul 2018, 12:12 bulk 88, <bulk88@hotmail.com> wrote:

>
> 32 bit perl generates different numbers in the mph hash than 64 bit
> perl. I'll guess more "use integer" is needed somewhere in the code.
>

Actually no, more use integer doesn't fix this and causes other issues.

The problem is that while use integer disables conversion to floating
point, which we *want*, it also causes the return from _fnv() to be
*signed* which then causes the minimum perfect hash construction to produce
surprising results. A simple fix on little endian boxen is to change the
return of _fnv() to

return unpack "V", pack "l", $h;

Which in my testing causes the 32bit builds to produce the same output as
the 64bit builds.

I am traveling right now so it's a bit difficult to do more than write this
mail. If no-one beats me to it I will push the patch when I return.

Fwiw, it would be nice to have a "no float_conversion" instead of "use
integer" for situations like this where we want to avoid floating point
conversion but where we do NOT want signed/integer semantics. "use integer"
affects too much and easily results in surprise, such as how it changes
the behaviour of the % (Modulo operator), which for instance causes an
infinite loop in the seed selection logic due to signedness issues.

Sigh.

Yves

--000000000000afb68c0570e27c65
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"auto"><div><div class=3D"gmail_quote"><div dir=3D"ltr">On Thu, =
5 Jul 2018, 12:12 bulk 88, &lt;<a href=3D"mailto:bulk88@hotmail.com">bulk88=
@hotmail.com</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
32 bit perl generates different numbers in the mph hash than 64 bit <br>
perl. I&#39;ll guess more &quot;use integer&quot; is needed somewhere in th=
e code.<br></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D=
"auto">Actually no, more use integer doesn&#39;t fix this and causes other =
issues.</div><div dir=3D"auto"><br></div><div dir=3D"auto">The problem is t=
hat while use integer disables conversion to floating point, which we *want=
*, it also causes the return from _fnv() to be *signed* which then causes t=
he minimum perfect hash construction to produce surprising results. A simpl=
e fix on little endian boxen is to change the return of _fnv() to=C2=A0</di=
v><div dir=3D"auto"><br></div><div dir=3D"auto">return unpack &quot;V&quot;=
, pack &quot;l&quot;, $h;</div><div dir=3D"auto"><br></div><div dir=3D"auto=
">Which in my testing causes the 32bit builds to produce the same output as=
 the 64bit builds.</div><div dir=3D"auto"><br></div><div dir=3D"auto">I am =
traveling right now so it&#39;s a bit difficult to do more than write this =
mail. If no-one beats me to it I will push the patch when I return.</div><d=
iv dir=3D"auto"><br></div><div dir=3D"auto">Fwiw, it would be nice to have =
a &quot;no float_conversion&quot; instead of &quot;use integer&quot; for si=
tuations like this where we want to avoid floating point conversion but whe=
re we do NOT want signed/integer semantics. &quot;use integer&quot; affects=
 too much and easily results in surprise, such as how it changes=C2=A0 the =
behaviour of the % (Modulo operator), which for instance causes an infinite=
 loop in the seed selection logic due to signedness issues.</div><div dir=
=3D"auto"><br></div><div dir=3D"auto">Sigh.</div><div dir=3D"auto"><br></di=
v><div dir=3D"auto">Yves</div><div dir=3D"auto"><br></div><div dir=3D"auto"=
><br></div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmai=
l_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>

--000000000000afb68c0570e27c65--
0
demerphq
7/13/2018 2:42:07 PM
On 07/13/2018 08:42 AM, demerphq wrote:
> On Thu, 5 Jul 2018, 12:12 bulk 88, <bulk88@hotmail.com 
> <mailto:bulk88@hotmail.com>> wrote:
> 
> 
>     32 bit perl generates different numbers in the mph hash than 64 bit
>     perl. I'll guess more "use integer" is needed somewhere in the code.
> 
> 
> Actually no, more use integer doesn't fix this and causes other issues.
> 
> The problem is that while use integer disables conversion to floating 
> point, which we *want*, it also causes the return from _fnv() to be 
> *signed* which then causes the minimum perfect hash construction to 
> produce surprising results. A simple fix on little endian boxen is to 
> change the return of _fnv() to
> 
> return unpack "V", pack "l", $h;
> 
> Which in my testing causes the 32bit builds to produce the same output 
> as the 64bit builds.
> 
> I am traveling right now so it's a bit difficult to do more than write 
> this mail. If no-one beats me to it I will push the patch when I return.

Last week I pushed 'use bignum' globally in the program in 
00d503c441212052333efea48fdca1499869a60c.

That solves the problem.  Any slowdown is inconsequential in perl's 
usage, as it is executed only during development, and even then only 
rarely (usually by me) when very particular things in the build change, 
such as getting a new Unicode release.

> 
> Fwiw, it would be nice to have a "no float_conversion" instead of "use 
> integer" for situations like this where we want to avoid floating point 
> conversion but where we do NOT want signed/integer semantics. "use 
> integer" affects too much and easily results in surprise, such as how it 
> changes  the behaviour of the % (Modulo operator), which for instance 
> causes an infinite loop in the seed selection logic due to signedness 
> issues.
> 
> Sigh.
> 
> Yves
> 
> 
> 
0
khw
7/13/2018 3:40:23 PM
Reply: