// 
// Decompiled by Procyon v0.6.0
// 

package io.sentry.util;

import java.util.concurrent.atomic.AtomicLong;
import org.jetbrains.annotations.ApiStatus;
import java.io.Serializable;

@ApiStatus.Internal
public final class Random implements Serializable
{
    private static final long serialVersionUID = -4257915988930727506L;
    static final AtomicLong UNIQUE_SEED;
    private static final long MULT_64 = 6364136223846793005L;
    private static final double DOUBLE_MASK = 9.007199254740992E15;
    private static final float FLOAT_UNIT = 1.6777216E7f;
    private static final long INTEGER_MASK = 4294967295L;
    private long state;
    private long inc;
    private boolean gausAvailable;
    private double nextGaus;
    
    public Random() {
        this(getRandomSeed(), getRandomSeed());
    }
    
    public Random(final long seed, final long streamNumber) {
        this.setSeed(seed, streamNumber);
    }
    
    private Random(final long initialState, final long increment, final boolean dummy) {
        this.setState(initialState);
        this.setInc(increment);
    }
    
    public void setSeed(final long seed, final long streamNumber) {
        this.state = 0L;
        this.inc = (streamNumber << 1 | 0x1L);
        this.state = this.state * 6364136223846793005L + this.inc;
        this.state += seed;
    }
    
    public byte nextByte() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return (byte)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) >>> 24);
    }
    
    public void nextBytes(final byte[] b) {
        for (int i = 0; i < b.length; ++i) {
            this.state = this.state * 6364136223846793005L + this.inc;
            b[i] = (byte)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) >>> 24);
        }
    }
    
    public char nextChar() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return (char)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) >>> 16);
    }
    
    public short nextShort() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return (short)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) >>> 16);
    }
    
    public int nextInt() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return (int)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L));
    }
    
    public int nextInt(final int n) {
        this.state = this.state * 6364136223846793005L + this.inc;
        int r = (int)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L)) >>> 1;
        final int m = n - 1;
        if ((n & m) == 0x0) {
            r = (int)(n * (long)r >> 31);
        }
        else {
            for (int u = r; u - (r = u % n) + m < 0; u = (int)((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L)) >>> 1) {
                this.state = this.state * 6364136223846793005L + this.inc;
            }
        }
        return r;
    }
    
    public boolean nextBoolean() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return ((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 31 != 0L;
    }
    
    public boolean nextBoolean(final double probability) {
        if (probability < 0.0 || probability > 1.0) {
            throw new IllegalArgumentException("probability must be between 0.0 and 1.0 inclusive.");
        }
        if (probability == 0.0) {
            return false;
        }
        if (probability == 1.0) {
            return true;
        }
        this.state = this.state * 6364136223846793005L + this.inc;
        final long l = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL;
        this.state = this.state * 6364136223846793005L + this.inc;
        return ((l >>> 6 << 27) + (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 5)) / 9.007199254740992E15 < probability;
    }
    
    public long nextLong() {
        this.state = this.state * 6364136223846793005L + this.inc;
        final long l = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L);
        this.state = this.state * 6364136223846793005L + this.inc;
        final long j = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L);
        return (l << 32) + (int)j;
    }
    
    public long nextLong(final long n) {
        if (n == 0L) {
            throw new IllegalArgumentException("n has to be greater than 0");
        }
        long bits;
        long val;
        do {
            this.state = this.state * 6364136223846793005L + this.inc;
            final long l = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L);
            this.state = this.state * 6364136223846793005L + this.inc;
            final long j = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L);
            bits = (l << 32) + (int)j >>> 1;
            val = bits % n;
        } while (bits - val + (n - 1L) < 0L);
        return val;
    }
    
    public double nextDouble() {
        this.state = this.state * 6364136223846793005L + this.inc;
        final long l = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL;
        this.state = this.state * 6364136223846793005L + this.inc;
        return ((l >>> 6 << 27) + (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 5)) / 9.007199254740992E15;
    }
    
    public double nextDouble(final boolean includeZero, final boolean includeOne) {
        double d = 0.0;
        do {
            this.state = this.state * 6364136223846793005L + this.inc;
            final long l = (this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL;
            this.state = this.state * 6364136223846793005L + this.inc;
            d = ((l >>> 6 << 27) + (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 5)) / 9.007199254740992E15;
            if (includeOne) {
                this.state = this.state * 6364136223846793005L + this.inc;
                if (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 31 == 0L) {
                    continue;
                }
                ++d;
            }
        } while (d > 1.0 || (!includeZero && d == 0.0));
        return d;
    }
    
    public float nextFloat() {
        this.state = this.state * 6364136223846793005L + this.inc;
        return (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 8) / 1.6777216E7f;
    }
    
    public float nextFloat(final boolean includeZero, final boolean includeOne) {
        float d = 0.0f;
        do {
            this.state = this.state * 6364136223846793005L + this.inc;
            d = (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 8) / 1.6777216E7f;
            if (includeOne) {
                this.state = this.state * 6364136223846793005L + this.inc;
                if (((this.state >>> 22 ^ this.state) >>> (int)((this.state >>> 61) + 22L) & 0xFFFFFFFFL) >>> 31 == 0L) {
                    continue;
                }
                ++d;
            }
        } while (d > 1.0f || (!includeZero && d == 0.0f));
        return d;
    }
    
    private void setInc(final long increment) {
        if (increment == 0L || increment % 2L == 0L) {
            throw new IllegalArgumentException("Increment may not be 0 or even. Value: " + increment);
        }
        this.inc = increment;
    }
    
    private void setState(final long state) {
        this.state = state;
    }
    
    private static long getRandomSeed() {
        long next;
        long current;
        do {
            current = (next = Random.UNIQUE_SEED.get());
            next ^= next >> 12;
            next ^= next << 25;
            next ^= next >> 27;
            next *= 2685821657736338717L;
        } while (!Random.UNIQUE_SEED.compareAndSet(current, next));
        return next;
    }
    
    static {
        UNIQUE_SEED = new AtomicLong(System.nanoTime());
    }
}
