{"id":1638,"date":"2021-05-31T12:46:46","date_gmt":"2021-05-31T10:46:46","guid":{"rendered":"https:\/\/moijari.com\/?p=1638"},"modified":"2021-06-20T21:21:04","modified_gmt":"2021-06-20T19:21:04","slug":"ressu-2-0-uusi-limitin-laskenta","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=1638","title":{"rendered":"Ressu 2.0 Uusi limitin laskenta"},"content":{"rendered":"\n<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. Edellinen posti j\u00e4i auki limitin laskennan osalta. Edellisess\u00e4 kokeiltiin sqrt() ja cbrt() funktioita, mutta todellisuudessa kumpikaan niist\u00e4 ei toimi halutulla tavalla. T\u00e4ss\u00e4 postissa limit lasketaan selailemalla vaihteluja alimmasta ylimp\u00e4\u00e4n, ja tarkastamalla onko edellinen vaihtelu*1.6 suurempi kun t\u00e4m\u00e4n kierroksen vaihtelu. T\u00e4ss\u00e4 postissa on my\u00f6s muutos debukkaustulosteeseen. Edellisess\u00e4 postissa kerroin ett\u00e4 kellojono koostuu perusmateriaalista ja pienist\u00e4 vaihteluista, joista j\u00e4lkimm\u00e4ist\u00e4 k\u00e4ytet\u00e4\u00e4n teoreettisten satunnaisbittien laskentaan. newressu.deb tulosteeseen on lis\u00e4tty merkkijono chains, joka listaa perusjonon t\u00e4htin\u00e4 ja pienemm\u00e4t vaihtelut numeroina.<\/p>\n\n\n\n<p>Jos haluat kokeilla edellisen postin satunnaislukulelua kopioi sen vaatimat rutiinit edellisest\u00e4 postista t\u00e4m\u00e4n generaattorin per\u00e4\u00e4n.<\/p>\n\n\n\n<p>Taas kerran vanha tuttu millisekuntien alimman merkin lukemiseen. T\u00e4ss\u00e4 rutiinissa on pieni muutos, joka tallettaa kellojonon newressu.deb raportin chains kentt\u00e4\u00e4 varten. (DEBUG4)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned long periods&#91;1024];\nunsigned long genbytes=0;\nunsigned long clockbytes=0;\n\n#define DEBUG2 2\n#define DEBUG4 2\n\n#ifdef DEBUG4\nunsigned char cc&#91;256*1048576]; \/\/ clock_chain\nunsigned char *ccp;\nint cc_bytes;\n#endif\n\nunsigned char ressu_clockbyte() \/* JariK 2013 *\/\n{\n  unsigned char c;\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  c=tv.tv_usec &amp; 0xff;\n#ifdef DEBUG4\n  if(cc_bytes&lt;sizeof(cc)) {\n    *ccp++ = c;\n    cc_bytes++;\n  }\n#endif\n  return(c);\n}<\/code><\/pre>\n\n\n\n<p>Seuraava rutiini on kuten edellisess\u00e4 postissa, se tekee yhden kierroksen satunnaisbittigeneraattoria. Huomaa ett\u00e4 t\u00e4ss\u00e4 yhteen kierrokseen kuuluvat kaikki kahdeksan bitti\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void ressu_genbytes_fast(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte();\n      if(prevbyte==-1)\n        prevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n        periods&#91;count]++;\n        clockbytes+=count;\n        count=0;\n        prevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>T\u00e4m\u00e4 on varsinainen asiakkaan k\u00e4ytt\u00e4m\u00e4 satunnaislukujen generointirutiini. Limitin laskennan muutos on while (ok) kappaleessa. Luuppi kiert\u00e4\u00e4 kelloketjut l\u00e4pi yksi kerrallaan pienimm\u00e4st\u00e4 suurimpaan. Jokaisesta kelloketjusta verrataan kelloketjujen lukum\u00e4\u00e4r\u00e4\u00e4 ja edellisten kelloketjujen lukum\u00e4\u00e4r\u00e4\u00e4. Jos kelloketjujen lukum\u00e4\u00e4r\u00e4 on pienempi kuin edellisten kelloketjujen lukum\u00e4\u00e4r\u00e4 * 1.6 kelloketju kuuluu pienten ketjujen joukkoon jos taas suurempi, se kuuluu ohitettavien kelloketjujen joukkoon. Limitiksi j\u00e4\u00e4 viimeinen kelvannut kelloketju.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define RESSUT_BYTES 4096\n#define RESSU_BITS_NEEDED 128\n#define RESSU_MIN_ROUNDS 2\n\nint ressu_bits_needed=RESSU_BITS_NEEDED;\nint ressut_bytes = RESSUT_BYTES;\n\nvoid ressu_genbytes(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n\n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n        memset(ressut,0,ressut_bytes);\n        ressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n        periods&#91;d]=0;\n\n#ifdef DEBUG4\n      ccp=cc;\n      cc_bytes=0;\n#endif\n\n#ifdef DEBUG2\n      while(ressu_clockbyte()!=0);\n      while(ressu_clockbyte()==0);\n#endif\n\n#ifdef DEBUG4\n      ccp=cc;\n      cc_bytes=0;\n#endif\n\n      int rndbits=0, rounds=0;\n      int lim1, lim2, lim3, lim=0;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n          d&lt;RESSU_MIN_ROUNDS; d++) {\n\n        rounds++;\n\n        ressu_genbytes_fast(ressut_bytes,ressut);\n\n        lim=1;\n\n        int ok=1, f, prevf=-1;\n        while(ok==1) {\n          ok=0;\n          f=-1;\n          for(e=0;e&lt;1024;e++) {\n            if(periods&#91;e]>lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n              f=periods&#91;e];\n            }\n          }\n          if(prevf==-1 || (f!=-1 &amp;&amp;f&lt;=(double)prevf*1.6)) {\n            lim=f;\n            prevf=f;\n            ok=1;\n          }\n        } \/\/ while(ok==1)\n        lim1=lim;\n\n        \/\/ find next greater than lim\n\n        f=-1;\n        for(e=0;e&lt;1024;e++) {\n          if(periods&#91;e]>lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n            f=periods&#91;e];\n        }\n        lim2=f;\n        lim=lim2;\n\n        int prev_rndbits=rndbits;\n        rndbits=0;\n        for(e=0;e&lt;1024;e++) {\n          if(periods&#91;e]>0 &amp;&amp; periods&#91;e]&lt;lim) {\n            rndbits+=periods&#91;e];\n          }\n        }\n\n        if(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n          clockbytes=0;\n          for(e=0;e&lt;1024;e++)\n            periods&#91;e]=0;\n          ccp=cc;\n          cc_bytes=0;\n          rndbits=0;\n        }\n      } \/\/ for(d=0;\n\n#ifdef DEBUG4\n      FILE *fp1;\n      if((fp1=fopen(\"newressu.deb\",\"a\"))!=NULL) {\n\n        for(d=0;d&lt;32;d++)\n          fprintf(fp1,\"%02x\",ressut&#91;d]);\n\n        fprintf(fp1,\", ressut_bytes: %d\",ressut_bytes);\n        fprintf(fp1,\", ressu_bits_needed: %d\",ressu_bits_needed);\n        fprintf(fp1,\", clockbytes: %ld\",clockbytes);\n\n        unsigned long total=0;\n        fprintf(fp1,\", fluctuations:\");\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]!=0) {\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n            total+=(periods&#91;d]*d);\n          }\n        }\n        fprintf(fp1,\", total: %lu\",total);\n\n        fprintf(fp1,\", limit1: %d\",lim1);\n        fprintf(fp1,\", limit2: %d\",lim2);\n\n        fprintf(fp1,\", limit: %d\",lim);\n\n        fprintf(fp1,\", skipped:\");\n\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]>=lim) {\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n          }\n        }\n\n        fprintf(fp1,\", counted:\");\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]>0 &amp;&amp; periods&#91;d]&lt;lim) {\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n          }\n        }\n        fprintf(fp1,\", rndbits: %d\",rndbits);\n        fprintf(fp1,\", rounds: %d\",rounds);\n\n        int prevbyte=-1, count=0, count2=0;\n        unsigned char byte, small=-1;\n        fprintf(fp1,\", chains:\");\n        for(d=0;d&lt;cc_bytes;d++) {\n          byte=cc&#91;d];\n          if(prevbyte==-1) {\n            prevbyte=byte;\n            count=1;\n          }\n          if(prevbyte!=byte) {\n            if(periods&#91;count]>=lim) {\n              if(small==1 || small==-1)\n                fprintf(fp1,\" *\");\n              small=0;\n            } else small=1;\n            if(small) {\n              fprintf(fp1,\" %d\",count);\n              count2++;\n            }\n            count=0;\n            prevbyte=byte;\n          }\n          count++;\n        }\n        if(small) {\n          fprintf(fp1,\" %d\",count);\n          count2++;\n        }\n        fprintf(fp1,\", count: %d\",count2);\n\n        fprintf(fp1,\"\\n\");\n        fflush(fp1);\n        fclose(fp1);\n      } \/\/ if((fp1=fopen\n#endif\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}\n<\/code><\/pre>\n\n\n\n<p>Seuraavassa esimerkki debukkailurivist\u00e4: bytes kertoo sis\u00e4isen puskurin koon. bits needed kertoo, kuinka monta pikkuketjua tarvitaan. clockbytes kertoo, kuinka paljon kelloketjua on k\u00e4ytetty. fluctuations kertoo t\u00e4m\u00e4n ressu ajon vaihtelut. total kertoo loppusumman fluctuations kent\u00e4st\u00e4. limit1 kertoo pikkuvaihtelujen suurimman arvon. limit2 kertoo isojen vaihtelujen pienimm\u00e4n kent\u00e4n. skipped luettelee ohitetut isot vaihtelut. counted taas listaa  teoreettisiin satunnaisbitteihin lasketut vaihtelut. rndbits kertoo counted kent\u00e4ss\u00e4 olevien ketjujen lukum\u00e4\u00e4r\u00e4n. rounds kertoo t\u00e4ll\u00e4 kerralla ajettujen kierrostan lukum\u00e4\u00e4\u00e4r\u00e4n. chains n\u00e4ytt\u00e4\u00e4 ajon kellojonojen rakenteen.<\/p>\n\n\n\n<p>Chainssissa perusmerkkijonoa kuvataan t\u00e4hdill\u00e4. T\u00e4hdill\u00e4 merkityt jonot ovat listassa ohitettujen alla. Numeroilla kuvataan pieni\u00e4 vaihteluita. Kuten sanottu kellojono on enimm\u00e4kseen perusmateriaalia, ja lyhyit\u00e4 jonoja on satunnaisesti koko kellojonon matkalla. Chains kent\u00e4n j\u00e4lkeen on count kentt\u00e4, joka kertoo lyhyiden ketjujen m\u00e4\u00e4r\u00e4n chains:issa. Count kentt\u00e4 py\u00f6ristyy yl\u00f6sp\u00e4in l\u00e4himp\u00e4\u00e4n kierrokseen, joten se on tavallisesti suurempi kuin bits_needed kentt\u00e4.<\/p>\n\n\n\n<p>82e936ee06841321134b74b2981f8df79a001999ee43bebb38f7302d77513ccc, ressut_bytes: 4096, ressu_bits_needed: 128, clockbytes: 163826, fluctuations: 1:16 2:10 3:11 4:10 5:10 6:21 7:10 8:10 9:15 10:12 11:9 12:25 13:2225 14:9558, total: 163826, limit1: 25, limit2: 2225, limit: 2225, skipped: 13:2225 14:9558, counted: 1:16 2:10 3:11 4:10 5:10 6:21 7:10 8:10 9:15 10:12 11:9 12:25, rndbits: 159, rounds: 5, chains: 10 * 10 5 * 7 6 * 10 5 * 7 8 * 12 8 * 4 10 * 2 5 * 9 5 * 3 * 9 4 * 8 6 * 9 * 9 1 * 3 1 * 11 1 * 2 8 * 4 10 * 6 1 * 11 3 * 7 * 4 10 * 9 12 * 1 12 * 9 12 * 2 12 * 10 * 2 12 * 6 * 6 8 * 1 6 * 7 1 * 12 * 6 10 * 1 12 * 7 11 * 12 * 6 1 6 * 12 * 12 * 11 4 * 12 * 7 3 * 3 * 9 6 * 8 6 * 3 5 * 9 6 * 6 12 * 1 12 * 2 12 * 2 12 * 9 10 * 4 10 * 2 6 * 6 1 5 * 12 * 12 * 12 12 * 1 * 4 11 * 3 * 12 2 * 4 * 3 * 5 * 9 6 * 7 6 * 10 6 * 3 3 * 1 9 * 12 1 * 11 * 9 1 * 2 * 12 * 9 8 * 5 10 * 7 8 * 6 8 * 12 * 5 2 * 11 4 * 6 11 * 1 12 * 4 5 * 7 7 * 9 3 * 8 6 * 10 11 *, count: 159<\/p>\n\n\n\n<p>Lopuksi viel\u00e4 generaattori ilman debukkailulauseita:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned long periods&#91;1024];\nunsigned long genbytes=0;\nunsigned long clockbytes=0;\n\nunsigned char ressu_clockbyte() \/* JariK 2013 *\/\n{\n  unsigned char c;\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  c=tv.tv_usec &amp; 0xff;\n  return(c);\n}\n\nvoid ressu_genbytes_fast(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte();\n      if(prevbyte==-1)\n        prevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n        periods&#91;count]++;\n        clockbytes+=count;\n        count=0;\n        prevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}\n\n#define RESSUT_BYTES 4096\n#define RESSU_BITS_NEEDED 128\n#define RESSU_MIN_ROUNDS 2\n\nint ressu_bits_needed=RESSU_BITS_NEEDED;\nint ressut_bytes = RESSUT_BYTES;\n\nvoid ressu_genbytes(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n\n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n        memset(ressut,0,ressut_bytes);\n        ressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n        periods&#91;d]=0;\n\n      int rndbits=0, lim;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n          d&lt;RESSU_MIN_ROUNDS; d++) {\n\n        ressu_genbytes_fast(ressut_bytes,ressut);\n\n        lim=1;\n\n        int ok=1, f, prevf=-1;\n\n        while(ok==1) {\n          ok=0;\n          f=-1;\n          for(e=0;e&lt;1024;e++) {\n            if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n              f=periods&#91;e];\n            }\n          }\n          if(prevf==-1 || f&lt;=(double)prevf*1.6) {\n            lim=f;\n            prevf=f;\n            ok=1;\n          }\n        }\n\n        \/\/ find next greater than lim\n\n        f=-1;\n        for(e=0;e&lt;1024;e++) {\n          if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n            f=periods&#91;e];\n        }\n        lim=f;\n\n        int prev_rndbits=rndbits;\n\n        rndbits=0;\n        for(e=0;e&lt;1024;e++) {\n          if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;lim) {\n            rndbits+=periods&#91;e];\n          }\n        }\n\n        if(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n          clockbytes=0;\n          for(e=0;e&lt;1024;e++)\n            periods&#91;e]=0;\n          rndbits=0;\n        }\n      } \/\/ for(d=0;\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n  genbytes+=size;\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. Edellinen posti j\u00e4i auki limitin laskennan osalta. Edellisess\u00e4 kokeiltiin sqrt() ja cbrt() funktioita, mutta todellisuudessa kumpikaan niist\u00e4 ei toimi halutulla tavalla. T\u00e4ss\u00e4 postissa limit lasketaan selailemalla vaihteluja alimmasta ylimp\u00e4\u00e4n, ja tarkastamalla onko edellinen vaihtelu*1.6 suurempi kun t\u00e4m\u00e4n kierroksen vaihtelu. T\u00e4ss\u00e4 postissa on my\u00f6s muutos debukkaustulosteeseen. Edellisess\u00e4 postissa kerroin ett\u00e4 kellojono koostuu perusmateriaalista&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=1638\">Continue reading <span class=\"screen-reader-text\">Ressu 2.0 Uusi limitin laskenta<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,11],"tags":[],"_links":{"self":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1638"}],"collection":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1638"}],"version-history":[{"count":12,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1638\/revisions"}],"predecessor-version":[{"id":1686,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1638\/revisions\/1686"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1638"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1638"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1638"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}