mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 01:23:24 -08:00
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [Installer] End a launcher that has no window to ask instead of prompting The in-app updater starts this installer detached and then closes itself. A client that accepts that close hides its window before it exits, and if it then hangs in shutdown there is nothing left to ask: the holder probe deliberately never posts WM_CLOSE to an instance it cannot see a window for, so the "ask it to close again" answer only repeated itself until the user picked Cancel and the installation aborted (Sentry COCKATRICE-DESKTOP-J). The launcher wait now asks the launcher itself before asking the user. A new probe mode, --close-launcher, answers whether that one process has a window a close could reach at all; it is limited to a pid that still runs from the directory being replaced, so a reused process id cannot be hit. When there is no window, the installer gives the shutdown it already started one full grace and then ends it through the handle it waited on, which is what the dialog's Yes answer did. The prompt remains for the case it exists for: a window is up, the instance may be waiting on its own question, and No now means only "keep waiting". The client is left alone: an already-installed version runs the installer during its own update, so a change there cannot reach the run that aborts. * [libcockatrice_rng] Include immintrin.h for AVX2 builds in SFMT --------- Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com>
327 lines
8.3 KiB
C
327 lines
8.3 KiB
C
#pragma once
|
|
/**
|
|
* @file SFMT.h
|
|
*
|
|
* @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom
|
|
* number generator using C structure.
|
|
*
|
|
* @author Mutsuo Saito (Hiroshima University)
|
|
* @author Makoto Matsumoto (The University of Tokyo)
|
|
*
|
|
* Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima
|
|
* University.
|
|
* Copyright (C) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima
|
|
* University and The University of Tokyo.
|
|
* All rights reserved.
|
|
*
|
|
* The 3-clause BSD License is applied to this software, see
|
|
* LICENSE.txt
|
|
*
|
|
* @note We assume that your system has inttypes.h. If your system
|
|
* doesn't have inttypes.h, you have to typedef uint32_t and uint64_t,
|
|
* and you have to define PRIu64 and PRIx64 in this file as follows:
|
|
* @verbatim
|
|
typedef unsigned int uint32_t
|
|
typedef unsigned long long uint64_t
|
|
#define PRIu64 "llu"
|
|
#define PRIx64 "llx"
|
|
@endverbatim
|
|
* uint32_t must be exactly 32-bit unsigned integer type (no more, no
|
|
* less), and uint64_t must be exactly 64-bit unsigned integer type.
|
|
* PRIu64 and PRIx64 are used for printf function to print 64-bit
|
|
* unsigned int and 64-bit unsigned int in hexadecimal format.
|
|
*/
|
|
|
|
#ifndef SFMTST_H
|
|
#define SFMTST_H
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
|
#include <inttypes.h>
|
|
#elif defined(_MSC_VER) || defined(__BORLANDC__)
|
|
typedef unsigned int uint32_t;
|
|
typedef unsigned __int64 uint64_t;
|
|
#define inline __inline
|
|
#else
|
|
#include <inttypes.h>
|
|
#if defined(__GNUC__)
|
|
#define inline __inline__
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef PRIu64
|
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
#define PRIu64 "I64u"
|
|
#define PRIx64 "I64x"
|
|
#else
|
|
#define PRIu64 "llu"
|
|
#define PRIx64 "llx"
|
|
#endif
|
|
#endif
|
|
|
|
#include "SFMT-params.h"
|
|
|
|
/*------------------------------------------
|
|
128-bit SIMD like data type for standard C
|
|
------------------------------------------*/
|
|
#if defined(HAVE_ALTIVEC)
|
|
#if !defined(__APPLE__)
|
|
#include <altivec.h>
|
|
#endif
|
|
/** 128-bit data structure */
|
|
union W128_T {
|
|
vector unsigned int s;
|
|
uint32_t u[4];
|
|
uint64_t u64[2];
|
|
};
|
|
#elif defined(HAVE_NEON)
|
|
#include <arm_neon.h>
|
|
|
|
/** 128-bit data structure */
|
|
union W128_T {
|
|
uint32_t u[4];
|
|
uint64_t u64[2];
|
|
uint32x4_t si;
|
|
};
|
|
//#elif defined(HAVE_SSE2)
|
|
#elif defined(HAVE_SSE2)
|
|
#if defined(__AVX2__)
|
|
#include <immintrin.h>
|
|
#else
|
|
#include <emmintrin.h>
|
|
#endif
|
|
|
|
/** 128-bit data structure */
|
|
union W128_T {
|
|
uint32_t u[4];
|
|
uint64_t u64[2];
|
|
__m128i si;
|
|
};
|
|
#else
|
|
/** 128-bit data structure */
|
|
union W128_T {
|
|
uint32_t u[4];
|
|
uint64_t u64[2];
|
|
};
|
|
#endif
|
|
|
|
/** 128-bit data type */
|
|
typedef union W128_T w128_t;
|
|
|
|
#if defined(__AVX2__)
|
|
/* The AVX2 state below names __m256i (and __m512i under AVX-512VL). The SIMD header
|
|
above is only pulled in for HAVE_SSE2, so a build that has __AVX2__ from the compiler
|
|
(e.g. -march=native) but not HAVE_SSE2 from the build system would otherwise not have
|
|
those types declared. */
|
|
#include <immintrin.h>
|
|
#endif
|
|
|
|
/**
|
|
* SFMT internal state
|
|
*/
|
|
struct SFMT_T {
|
|
#if defined(__AVX2__)
|
|
union {
|
|
w128_t state[SFMT_N];
|
|
__m256i state_ymm[SFMT_N/2];
|
|
#if defined(__AVX512VL__)
|
|
__m512i state_zmm[SFMT_N/4];
|
|
#endif
|
|
};
|
|
#else
|
|
/** the 128-bit internal state array */
|
|
w128_t state[SFMT_N];
|
|
#endif
|
|
/** index counter to the 32-bit internal state array */
|
|
int idx;
|
|
};
|
|
|
|
typedef struct SFMT_T sfmt_t;
|
|
|
|
void sfmt_fill_array32(sfmt_t * sfmt, uint32_t * array, int size);
|
|
void sfmt_fill_array64(sfmt_t * sfmt, uint64_t * array, int size);
|
|
void sfmt_init_gen_rand(sfmt_t * sfmt, uint32_t seed);
|
|
void sfmt_init_by_array(sfmt_t * sfmt, uint32_t * init_key, int key_length);
|
|
const char * sfmt_get_idstring(sfmt_t * sfmt);
|
|
int sfmt_get_min_array_size32(sfmt_t * sfmt);
|
|
int sfmt_get_min_array_size64(sfmt_t * sfmt);
|
|
void sfmt_gen_rand_all(sfmt_t * sfmt);
|
|
|
|
#ifndef ONLY64
|
|
/**
|
|
* This function generates and returns 32-bit pseudorandom number.
|
|
* init_gen_rand or init_by_array must be called before this function.
|
|
* @param sfmt SFMT internal state
|
|
* @return 32-bit pseudorandom number
|
|
*/
|
|
inline static uint32_t sfmt_genrand_uint32(sfmt_t * sfmt) {
|
|
uint32_t r;
|
|
uint32_t * psfmt32 = &sfmt->state[0].u[0];
|
|
|
|
if (sfmt->idx >= SFMT_N32) {
|
|
sfmt_gen_rand_all(sfmt);
|
|
sfmt->idx = 0;
|
|
}
|
|
r = psfmt32[sfmt->idx++];
|
|
return r;
|
|
}
|
|
#endif
|
|
/**
|
|
* This function generates and returns 64-bit pseudorandom number.
|
|
* init_gen_rand or init_by_array must be called before this function.
|
|
* The function gen_rand64 should not be called after gen_rand32,
|
|
* unless an initialization is again executed.
|
|
* @param sfmt SFMT internal state
|
|
* @return 64-bit pseudorandom number
|
|
*/
|
|
inline static uint64_t sfmt_genrand_uint64(sfmt_t * sfmt) {
|
|
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
|
uint32_t * psfmt32 = &sfmt->state[0].u[0];
|
|
uint32_t r1, r2;
|
|
#else
|
|
uint64_t r;
|
|
#endif
|
|
uint64_t * psfmt64 = &sfmt->state[0].u64[0];
|
|
assert(sfmt->idx % 2 == 0);
|
|
|
|
if (sfmt->idx >= SFMT_N32) {
|
|
sfmt_gen_rand_all(sfmt);
|
|
sfmt->idx = 0;
|
|
}
|
|
#if defined(BIG_ENDIAN64) && !defined(ONLY64)
|
|
r1 = psfmt32[sfmt->idx];
|
|
r2 = psfmt32[sfmt->idx + 1];
|
|
sfmt->idx += 2;
|
|
return ((uint64_t)r2 << 32) | r1;
|
|
#else
|
|
r = psfmt64[sfmt->idx / 2];
|
|
sfmt->idx += 2;
|
|
return r;
|
|
#endif
|
|
}
|
|
|
|
/* =================================================
|
|
The following real versions are due to Isaku Wada
|
|
================================================= */
|
|
/**
|
|
* converts an unsigned 32-bit number to a double on [0,1]-real-interval.
|
|
* @param v 32-bit unsigned integer
|
|
* @return double on [0,1]-real-interval
|
|
*/
|
|
inline static double sfmt_to_real1(uint32_t v)
|
|
{
|
|
return v * (1.0/4294967295.0);
|
|
/* divided by 2^32-1 */
|
|
}
|
|
|
|
/**
|
|
* generates a random number on [0,1]-real-interval
|
|
* @param sfmt SFMT internal state
|
|
* @return double on [0,1]-real-interval
|
|
*/
|
|
inline static double sfmt_genrand_real1(sfmt_t * sfmt)
|
|
{
|
|
return sfmt_to_real1(sfmt_genrand_uint32(sfmt));
|
|
}
|
|
|
|
/**
|
|
* converts an unsigned 32-bit integer to a double on [0,1)-real-interval.
|
|
* @param v 32-bit unsigned integer
|
|
* @return double on [0,1)-real-interval
|
|
*/
|
|
inline static double sfmt_to_real2(uint32_t v)
|
|
{
|
|
return v * (1.0/4294967296.0);
|
|
/* divided by 2^32 */
|
|
}
|
|
|
|
/**
|
|
* generates a random number on [0,1)-real-interval
|
|
* @param sfmt SFMT internal state
|
|
* @return double on [0,1)-real-interval
|
|
*/
|
|
inline static double sfmt_genrand_real2(sfmt_t * sfmt)
|
|
{
|
|
return sfmt_to_real2(sfmt_genrand_uint32(sfmt));
|
|
}
|
|
|
|
/**
|
|
* converts an unsigned 32-bit integer to a double on (0,1)-real-interval.
|
|
* @param v 32-bit unsigned integer
|
|
* @return double on (0,1)-real-interval
|
|
*/
|
|
inline static double sfmt_to_real3(uint32_t v)
|
|
{
|
|
return (((double)v) + 0.5)*(1.0/4294967296.0);
|
|
/* divided by 2^32 */
|
|
}
|
|
|
|
/**
|
|
* generates a random number on (0,1)-real-interval
|
|
* @param sfmt SFMT internal state
|
|
* @return double on (0,1)-real-interval
|
|
*/
|
|
inline static double sfmt_genrand_real3(sfmt_t * sfmt)
|
|
{
|
|
return sfmt_to_real3(sfmt_genrand_uint32(sfmt));
|
|
}
|
|
|
|
/**
|
|
* converts an unsigned 64-bit integer to double on [0,1)
|
|
* with 53-bit resolution.
|
|
* @param v 64-bit unsigned integer
|
|
* @return double on [0,1)-real-interval with 53-bit resolution.
|
|
*/
|
|
inline static double sfmt_to_res53(uint64_t v)
|
|
{
|
|
return (v >> 11) * (1.0/9007199254740992.0);
|
|
}
|
|
|
|
/**
|
|
* generates a random number on [0,1) with 53-bit resolution
|
|
* @param sfmt SFMT internal state
|
|
* @return double on [0,1) with 53-bit resolution
|
|
*/
|
|
inline static double sfmt_genrand_res53(sfmt_t * sfmt)
|
|
{
|
|
return sfmt_to_res53(sfmt_genrand_uint64(sfmt));
|
|
}
|
|
|
|
|
|
/* =================================================
|
|
The following function are added by Saito.
|
|
================================================= */
|
|
/**
|
|
* generates a random number on [0,1) with 53-bit resolution from two
|
|
* 32 bit integers
|
|
*/
|
|
inline static double sfmt_to_res53_mix(uint32_t x, uint32_t y)
|
|
{
|
|
return sfmt_to_res53(x | ((uint64_t)y << 32));
|
|
}
|
|
|
|
/**
|
|
* generates a random number on [0,1) with 53-bit resolution
|
|
* using two 32bit integers.
|
|
* @param sfmt SFMT internal state
|
|
* @return double on [0,1) with 53-bit resolution
|
|
*/
|
|
inline static double sfmt_genrand_res53_mix(sfmt_t * sfmt)
|
|
{
|
|
uint32_t x, y;
|
|
|
|
x = sfmt_genrand_uint32(sfmt);
|
|
y = sfmt_genrand_uint32(sfmt);
|
|
return sfmt_to_res53_mix(x, y);
|
|
}
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif
|