LCOV - code coverage report
Current view: top level - Core - legacy_random.c (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 35 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : legacy_random.c
       4             : 
       5             : 
       6             : Oolite
       7             : Copyright (C) 2004-2008 Giles C Williams and contributors
       8             : 
       9             : This program is free software; you can redistribute it and/or
      10             : modify it under the terms of the GNU General Public License
      11             : as published by the Free Software Foundation; either version 2
      12             : of the License, or (at your option) any later version.
      13             : 
      14             : This program is distributed in the hope that it will be useful,
      15             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             : GNU General Public License for more details.
      18             : 
      19             : You should have received a copy of the GNU General Public License
      20             : along with this program; if not, write to the Free Software
      21             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      22             : MA 02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : #include <stdio.h>
      27             : #include <math.h>
      28             : #include <stdint.h>
      29             : #include <stdbool.h>
      30             : #include <assert.h>
      31             : #include "legacy_random.h"
      32             : 
      33             : 
      34           0 : const Random_Seed       kNilRandomSeed = {0};
      35             : 
      36             : 
      37           0 : static RNG_Seed         rnd_seed;
      38             : 
      39             : 
      40             : // TODO: Why is this based on a static? Should change to OOMungeCheckSum(&checkSum, value);
      41           0 : static int32_t checksum;
      42           0 : void clear_checksum()
      43             : {
      44             :         checksum = 0;
      45             : }
      46             : 
      47             : 
      48           0 : int16_t munge_checksum(long long value_)
      49             : {
      50             :         uint32_t value = (uint32_t)value_;
      51             :         int32_t mult1 = (value & 15) + 8;
      52             :         checksum += value;
      53             :         checksum *= mult1;
      54             :         checksum += mult1;
      55             :         checksum &= 0xffff;
      56             :         return checksum;
      57             : }
      58             : 
      59             : 
      60             : // cunning price rounding routine:
      61             : //
      62           0 : double cunningFee(double value, double precision)
      63             : {
      64             :         double fee = value;
      65             :         double superfee = 100000.0;
      66             :         double max = 1 + precision;
      67             :         double min = 1 - precision;
      68             :         unsigned long long rounded_fee = superfee * floor(0.5 + fee / superfee);
      69             :         if (rounded_fee == 0)  rounded_fee = 1;
      70             :         double ratio = fee / (double)rounded_fee;
      71             :         
      72             :         while ((ratio < min || ratio > max) && superfee > 1)
      73             :         {
      74             :                 rounded_fee = superfee * floor(0.5 + fee / superfee);
      75             :                 if (rounded_fee == 0)  rounded_fee = 1;
      76             :                 ratio = fee / (double)rounded_fee;
      77             :                 superfee /= 10.0;
      78             :         }
      79             :         
      80             :         if (ratio > min && ratio < max)
      81             :                 fee = rounded_fee;
      82             :         
      83             :         return fee;
      84             : }
      85             : 
      86             : 
      87             : // an implementation of RANROT
      88             : // pseudo random number generator
      89             : //
      90           0 : static RANROTSeed               sRANROT;
      91             : 
      92             : 
      93           0 : unsigned Ranrot(void)
      94             : {
      95             :         sRANROT.high = (sRANROT.high << 16) + (sRANROT.high >> 16);
      96             :         sRANROT.high += sRANROT.low;
      97             :         sRANROT.low += sRANROT.high;
      98             :         return sRANROT.high & 0x7FFFFFFF;
      99             : }
     100             : 
     101             : 
     102           0 : unsigned RanrotWithSeed(RANROTSeed *ioSeed)
     103             : {
     104             :         assert(ioSeed != NULL);
     105             :         
     106             :         ioSeed->high = (ioSeed->high << 16) + (ioSeed->high >> 16);
     107             :         ioSeed->high += ioSeed->low;
     108             :         ioSeed->low += ioSeed->high;
     109             :         return ioSeed->high & 0x7FFFFFFF;
     110             : }
     111             : 
     112             : 
     113           0 : RANROTSeed MakeRanrotSeed(uint32_t seed)
     114             : {
     115             :         RANROTSeed result =
     116             :         {
     117             :                 .low = seed,
     118             :                 .high = ~seed
     119             :         };
     120             :         
     121             :         // Mix it up a bit.
     122             :         RanrotWithSeed(&result);
     123             :         RanrotWithSeed(&result);
     124             :         RanrotWithSeed(&result);
     125             : 
     126             :         return result;
     127             : }
     128             : 
     129             : 
     130           0 : RANROTSeed RanrotSeedFromRNGSeed(RNG_Seed seed)
     131             : {
     132             :         return MakeRanrotSeed(seed.a * 0x1000000 + seed.b * 0x10000 + seed.c * 0x100 + seed.d);
     133             : }
     134             : 
     135             : 
     136           0 : RANROTSeed RanrotSeedFromRandomSeed(Random_Seed seed)
     137             : {
     138             :         // Same pattern as seed_for_planet_description().
     139             :         RNG_Seed s =
     140             :         {
     141             :                 .a = seed.c,
     142             :                 .b = seed.d,
     143             :                 .c = seed.e,
     144             :                 .d = seed.f
     145             :         };
     146             :         return RanrotSeedFromRNGSeed(s);
     147             : }
     148             : 
     149             : 
     150           0 : void ranrot_srand(uint32_t seed)
     151             : {
     152             :         sRANROT = MakeRanrotSeed(seed);
     153             : }
     154             : 
     155             : 
     156           0 : float randf (void)
     157             : {
     158             :         return (Ranrot() & 0xffff) * (1.0f / 65536.0f);
     159             : }
     160             : 
     161             : 
     162           0 : float randfWithSeed(RANROTSeed *ioSeed)
     163             : {
     164             :         return (RanrotWithSeed(ioSeed) & 0xffff) * (1.0f / 65536.0f);
     165             : }
     166             : 
     167             : 
     168           0 : float bellf (int n)
     169             : {
     170             :         int i = n;
     171             :         float total = 0;
     172             :         
     173             :         if (EXPECT_NOT(i <= 0))
     174             :         {
     175             :                 printf("***** ERROR - attempt to generate bellf(%d)\n", n);
     176             :                 return 0.0f; // catch possible div-by-zero problem
     177             :         }
     178             :         
     179             :         while (i-- > 0)
     180             :                 total += (Ranrot() & 1023);
     181             :         return total / (1024.0f * n);
     182             : }
     183             : 
     184             : 
     185           0 : RANROTSeed RANROTGetFullSeed(void)
     186             : {
     187             :         return sRANROT;
     188             : }
     189             : 
     190             : 
     191           0 : void RANROTSetFullSeed(RANROTSeed seed)
     192             : {
     193             :         sRANROT = seed;
     194             : }
     195             : 
     196             : 
     197           0 : void seed_RNG_only_for_planet_description (Random_Seed s_seed)
     198             : {
     199             :         rnd_seed.a = s_seed.c;
     200             :         rnd_seed.b = s_seed.d;
     201             :         rnd_seed.c = s_seed.e;
     202             :         rnd_seed.d = s_seed.f;
     203             : }
     204             : 
     205             : 
     206           0 : void seed_for_planet_description (Random_Seed s_seed)
     207             : {
     208             :         seed_RNG_only_for_planet_description(s_seed);
     209             :         sRANROT = RanrotSeedFromRNGSeed(rnd_seed);
     210             : }
     211             : 
     212             : 
     213           0 : RNG_Seed currentRandomSeed (void)
     214             : {
     215             :         return rnd_seed;
     216             : }
     217             : 
     218             : 
     219           0 : void setRandomSeed (RNG_Seed a_seed)
     220             : {
     221             :         rnd_seed = a_seed;
     222             : }
     223             : 
     224             : 
     225           0 : int gen_rnd_number (void)
     226             : {
     227             :         int a,x;
     228             :         
     229             :         x = (rnd_seed.a * 2) & 0xFF;
     230             :         a = x + rnd_seed.c;
     231             :         if (rnd_seed.a > 127)
     232             :                 a++;
     233             :         rnd_seed.a = a & 0xFF;
     234             :         rnd_seed.c = x;
     235             :         
     236             :         a = a / 256;    /* a = any carry left from above */
     237             :         x = rnd_seed.b;
     238             :         a = (a + x + rnd_seed.d) & 0xFF;
     239             :         rnd_seed.b = a;
     240             :         rnd_seed.d = x;
     241             :         return a;
     242             : }
     243             : 
     244             : 
     245           0 : static bool sReallyRandomInited = false;
     246           0 : static RANROTSeed sReallyRandomSeed;
     247             : 
     248             : 
     249           0 : uint32_t OOReallyRandom(void)
     250             : {
     251             :         assert(sReallyRandomInited);
     252             :         return RanrotWithSeed(&sReallyRandomSeed);
     253             : }
     254             : 
     255             : 
     256           0 : void OOInitReallyRandom(uint64_t seed)
     257             : {
     258             :         assert(!sReallyRandomInited);
     259             :         seed ^= 0xA471D52AEF3B6322ULL;
     260             :         sReallyRandomSeed.high = (seed >> 32) & 0xFFFFFFFF;
     261             :         sReallyRandomSeed.low = seed  & 0xFFFFFFFF;
     262             :         sReallyRandomInited = true;
     263             :         OOReallyRandom();
     264             : }
     265             : 
     266             : 
     267           0 : void OOSetReallyRandomRANROTSeed(void)
     268             : {
     269             :         assert(sReallyRandomInited);
     270             :         sRANROT = sReallyRandomSeed;
     271             :         OOReallyRandom();       // Don't go reusing it.
     272             : }
     273             : 
     274             : 
     275           0 : void OOSetReallyRandomRndSeed(void)
     276             : {
     277             :         uint32_t val = OOReallyRandom();
     278             :         rnd_seed.a = (val >> 24) & 0xFF;
     279             :         rnd_seed.b = (val >> 16) & 0xFF;
     280             :         rnd_seed.c = (val >> 8) & 0xFF;
     281             :         rnd_seed.d = val & 0xFF;
     282             : }
     283             : 
     284             : 
     285           0 : void OOSetReallyRandomRANROTAndRndSeeds(void)
     286             : {
     287             :         OOSetReallyRandomRANROTSeed();
     288             :         OOSetReallyRandomRndSeed();
     289             : }
     290             : 
     291             : 
     292           0 : OORandomState OOSaveRandomState(void)
     293             : {
     294             :         return (OORandomState)
     295             :         {
     296             :                 .ranrot = sRANROT,
     297             :                 .rnd = rnd_seed
     298             :         };
     299             : }
     300             : 
     301             : 
     302           0 : void OORestoreRandomState(OORandomState state)
     303             : {
     304             :         sRANROT = state.ranrot;
     305             :         rnd_seed = state.rnd;
     306             : }
     307             : 
     308             : 
     309           0 : void make_pseudo_random_seed (Random_Seed *seed_ptr)
     310             : {
     311             :         seed_ptr->a = gen_rnd_number();
     312             :         seed_ptr->b = gen_rnd_number();
     313             :         seed_ptr->c = gen_rnd_number();
     314             :         seed_ptr->d = gen_rnd_number();
     315             :         seed_ptr->e = gen_rnd_number();
     316             :         seed_ptr->f = gen_rnd_number();
     317             : }
     318             : 
     319             : 
     320           0 : void rotate_seed (Random_Seed *seed_ptr)
     321             : {
     322             :         uint_fast16_t x;
     323             :         uint_fast16_t y;
     324             :         
     325             :         /*      Note: this is equivalent to adding three (little-endian) 16-bit values
     326             :                 together, rotating the three numbers and replacing one of them with
     327             :                 the sum. The byte-oriented approach is presumably because it was
     328             :                 reverse-engineered from eight-bit machine code. Switching to a plain
     329             :                 sixteen-bit representation is more trouble than it's worth since so
     330             :                 much code uses byte values from the seed struct directly.
     331             :         */
     332             :         x = seed_ptr->a + seed_ptr->c + seed_ptr->e;
     333             :         y = seed_ptr->b + seed_ptr->d + seed_ptr->f;
     334             :         
     335             :         seed_ptr->a = seed_ptr->c;
     336             :         seed_ptr->b = seed_ptr->d;
     337             :         
     338             :         seed_ptr->c = seed_ptr->e;
     339             :         seed_ptr->d = seed_ptr->f;
     340             :         
     341             :         seed_ptr->e = x;
     342             :         seed_ptr->f = y + (x >> 8);
     343             : }

Generated by: LCOV version 1.14