LCOV - code coverage report
Current view: top level - src - rng.c (source / functions) Coverage Total Hit
Test: poporon Coverage Report Lines: 98.2 % 55 54
Test Date: 2026-03-07 15:16:43 Functions: 100.0 % 7 7
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * libpoporon - rng.c
       3              :  *
       4              :  * This file is part of libpoporon.
       5              :  *
       6              :  * Author: Go Kudo <zeriyoshi@gmail.com>
       7              :  * SPDX-License-Identifier: BSD-3-Clause
       8              :  */
       9              : 
      10              : #include <stdlib.h>
      11              : #include <string.h>
      12              : 
      13              : #include <poporon/rng.h>
      14              : 
      15              : #include "internal/common.h"
      16              : 
      17              : #define SPLITMIX32_CONST_0 0x6C078965U
      18              : #define SPLITMIX32_CONST_1 0x9D2C5680U
      19              : #define SPLITMIX32_CONST_2 0xEFC60000U
      20              : #define SPLITMIX32_CONST_3 0x12345678U
      21              : 
      22              : struct _poporon_rng_t {
      23              :     poporon_rng_type_t type;
      24              :     uint32_t s[4];
      25              : };
      26              : 
      27       783824 : static inline uint32_t rotl(uint32_t x, int k)
      28              : {
      29       783824 :     return (x << k) | (x >> (32 - k));
      30              : }
      31              : 
      32          504 : static inline uint32_t splitmix32(uint32_t z)
      33              : {
      34          504 :     z = (z ^ (z >> 16)) * 0x85EBCA6BU;
      35          504 :     z = (z ^ (z >> 13)) * 0xC2B2AE35U;
      36          504 :     return z ^ (z >> 16);
      37              : }
      38              : 
      39          126 : static inline void xoshiro128pp_init(poporon_rng_t *rng, const void *seed, size_t seed_size)
      40              : {
      41              :     uint32_t s, z;
      42              : 
      43          126 :     s = 0;
      44          126 :     if (seed && seed_size > 0) {
      45          125 :         memcpy(&s, seed, seed_size < sizeof(uint32_t) ? seed_size : sizeof(uint32_t));
      46              :     }
      47              : 
      48          126 :     z = s + SPLITMIX32_CONST_0;
      49          126 :     rng->s[0] = splitmix32(z);
      50              : 
      51          126 :     z = rng->s[0] + SPLITMIX32_CONST_1;
      52          126 :     rng->s[1] = splitmix32(z);
      53              : 
      54          126 :     z = rng->s[1] + SPLITMIX32_CONST_2;
      55          126 :     rng->s[2] = splitmix32(z);
      56              : 
      57          126 :     z = rng->s[2] + SPLITMIX32_CONST_3;
      58          126 :     rng->s[3] = splitmix32(z);
      59          126 : }
      60              : 
      61       391912 : static inline uint32_t xoshiro128pp_next(poporon_rng_t *rng)
      62              : {
      63              :     uint32_t result, t;
      64              : 
      65       391912 :     result = rotl(rng->s[0] + rng->s[3], 7) + rng->s[0];
      66       391912 :     t = rng->s[1] << 9;
      67              : 
      68       391912 :     rng->s[2] ^= rng->s[0];
      69       391912 :     rng->s[3] ^= rng->s[1];
      70       391912 :     rng->s[1] ^= rng->s[2];
      71       391912 :     rng->s[0] ^= rng->s[3];
      72       391912 :     rng->s[2] ^= t;
      73       391912 :     rng->s[3] = rotl(rng->s[3], 11);
      74              : 
      75       391912 :     return result;
      76              : }
      77              : 
      78          126 : extern poporon_rng_t *poporon_rng_create(poporon_rng_type_t type, void *seed, size_t seed_size)
      79              : {
      80              :     poporon_rng_t *rng;
      81              : 
      82          126 :     rng = (poporon_rng_t *)pcalloc(1, sizeof(poporon_rng_t));
      83          126 :     if (!rng) {
      84            0 :         return NULL;
      85              :     }
      86              : 
      87          126 :     rng->type = type;
      88              : 
      89              :     switch (type) {
      90              :     case XOSHIRO128PP:
      91              :     default:
      92          126 :         xoshiro128pp_init(rng, seed, seed_size);
      93          126 :         break;
      94              :     }
      95              : 
      96          126 :     return rng;
      97              : }
      98              : 
      99          127 : extern void poporon_rng_destroy(poporon_rng_t *rng)
     100              : {
     101          127 :     if (rng) {
     102          126 :         pfree(rng);
     103              :     }
     104          127 : }
     105              : 
     106       391911 : extern bool poporon_rng_next(poporon_rng_t *rng, void *dest, size_t size)
     107              : {
     108              :     uint8_t *p;
     109              :     uint32_t val;
     110              :     size_t i, remaining;
     111              : 
     112       391911 :     if (!rng || !dest || size == 0) {
     113            3 :         return false;
     114              :     }
     115              : 
     116       391908 :     p = (uint8_t *)dest;
     117       391908 :     i = 0;
     118              : 
     119       783818 :     while (i + 4 <= size) {
     120       391910 :         val = xoshiro128pp_next(rng);
     121       391910 :         pmemcpy(p + i, &val, 4);
     122       391910 :         i += 4;
     123              :     }
     124              : 
     125       391908 :     remaining = size - i;
     126       391908 :     if (remaining > 0) {
     127            2 :         val = xoshiro128pp_next(rng);
     128            2 :         pmemcpy(p + i, &val, remaining);
     129              :     }
     130              : 
     131       391908 :     return true;
     132              : }
        

Generated by: LCOV version 2.0-1