⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 random.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
template<> Double Random12<true,true,Double>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Generate bits
    SizedUnsignedInteger<64>::Type r12 = Accessor<64>::getRandomInt(state);

    // Keep 2^52 + 1 possibilities
    // See comment in Simple version
    // allow %= only for 64-bit register machines
#if STREFLOP_RANDOM_GEN_SIZE == 64
    r12 %= 0x0010000000000001ULL;
#else
    // Choose to avoid % operator by having about 1/2 chance of rejection. Is this faster?
    while ((r12 &= 0x001FFFFFFFFFFFFFULL) > 0x0010000000000000ULL) r12 = Accessor<64>::getRandomInt(state);
#endif

    // bitwise add exponent so it's in the [1.0-2.0] range
    r12 += 0x3FF0000000000000ULL;

    return *reinterpret_cast<Double*>(&r12);
}

// Random in a 1..2 - need to exclude both bounds
template<> Double Random12<false,false,Double>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Generate bits
    SizedUnsignedInteger<64>::Type r12 = Accessor<64>::getRandomInt(state);

    // Keep 2^52 - 1 possibilities
    // See comment in Simple version
    // r12 %= 0x000FFFFFFFFFFFFFULL;
    // Choose to avoid % operator by having very small chance of rejection
    while ((r12 &= 0x000FFFFFFFFFFFFFULL) == 0x000FFFFFFFFFFFFFULL) r12 = Accessor<64>::getRandomInt(state);

    // bitwise add exponent so it's in the (1.0-2.0) range
    r12 += 0x3FF0000000000001ULL;

    return *reinterpret_cast<Double*>(&r12);
}


#ifdef Extended

// little endian
#if __FLOAT_WORD_ORDER == 1234

/// Little endian is fine, always the same offsets whatever the memory model
template<int Nbytes> struct ExtendedConverter {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+8);
    }
    // Mantissa
    static inline SizedUnsignedInteger<64>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<64>::Type*>(e);
    }
};

// Big endian
#elif __FLOAT_WORD_ORDER == 4321
template<int Nbytes> struct ExtendedConverter {
}

/// Extended is softfloat
template<> struct ExtendedConverter<10> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(e);
    }
    // Mantissa
    static inline SizedUnsignedInteger<64>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<64>::Type*>(reinterpret_cast<char*>(e)+2);
    }
};

/// Default gcc model for x87 - 32 bits (or with -m96bit-long-double)
template<> struct ExtendedConverter<12> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+2);
    }
    // Mantissa
    static inline SizedUnsignedInteger<64>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<64>::Type*>(reinterpret_cast<char*>(e)+4);
    }
};

/// Default gcc model for x87 - 64 bits (or with -m128bit-long-double)
template<> struct ExtendedConverter<16> {
    // Sign and exponent
    static inline SizedUnsignedInteger<16>::Type* sexpPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<16>::Type*>(reinterpret_cast<char*>(e)+6);
    }
    // Mantissa
    static inline SizedUnsignedInteger<64>::Type* mPtr(Extended* e) {
        return reinterpret_cast<SizedUnsignedInteger<64>::Type*>(reinterpret_cast<char*>(e)+8);
    }
};
#else
#error unknown byte order
#endif


// Return a random float
template<> Extended Random<Extended>(RandomState& state) {
    // Work directly on Extended bits
    Extended ret;

    // Generate 63 bits for the mantissa
    *ExtendedConverter<sizeof(Extended)>::mPtr(&ret) = Accessor<64>::getRandomInt(state);

    // Generate 16 bits for the exponent
    *ExtendedConverter<sizeof(Extended)>::sexpPtr(&ret) = Accessor<16>::getRandomInt(state);

    // Discard NaNs and Inf, ignore sign
    while ((*ExtendedConverter<sizeof(Extended)>::sexpPtr(&ret) & 0x7fff) == 0x7fff)
        *ExtendedConverter<sizeof(Extended)>::sexpPtr(&ret) = Accessor<16>::getRandomInt(state);

    // x87 extended format oddity: the first mantissa bit (always 1 for normal numbers) is visible, not hidden!
    if ((*ExtendedConverter<sizeof(Extended)>::sexpPtr(&ret) & 0x7fff) != 0)
        *ExtendedConverter<sizeof(Extended)>::mPtr(&ret) |= 0x8000000000000000ULL;

    return ret;
}


// Random in 1..2 - ideal IE case
template<> Extended Random12<true,false,Extended>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Work directly on Extended bits
    Extended r12;

    // Generate 63 bits for the mantissa
    *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) = Accessor<64>::getRandomInt(state);

    // x87 extended format oddity: the first mantissa bit (always 1 for normal numbers) is visible, not hidden!
    // Since in this case this is a number between 1 and 2, this bit has to be set explicitly
    *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) |= 0x8000000000000000ULL;

    // Set exponent so it's in the [1.0-2.0) range
    *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x3FFF;

    // scale from 1-2 interval to the desired interval
    return r12;
}

// Random in 1..2 - near ideal EI case
template<> Extended Random12<false,true,Extended>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Work directly on Extended bits
    Extended r12;

    // Generate 63 bits for the mantissa
    *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) = Accessor<64>::getRandomInt(state);

    // x87 extended format oddity: the first mantissa bit (always 1 for normal numbers) is visible, not hidden!
    // Since in this case this is a number between 1 and 2, this bit has to be set explicitly
    *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) |= 0x8000000000000000LL;

    // Set exponent so it's in the (1.0-2.0] range
    // Replace 1.0 by 2.0
    if (*ExtendedConverter<sizeof(Extended)>::mPtr(&r12) == 0x8000000000000000LL)
        *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x4000;
    else
        *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x3FFF;

    return r12;
}

// Random in 1..2 - need to include both bounds
template<> Extended Random12<true,true,Extended>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Work directly on Extended bits
    Extended r12;

    // Generate 64 bits for the mantissa
    do {
        *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) = Accessor<64>::getRandomInt(state);
    }
    // Include both bounds : repeat the random get till it's in the desired range
    // Keep the possibility for 2.0 in addition to all [1.0-2.0)
    while (*ExtendedConverter<sizeof(Extended)>::mPtr(&r12) > 0x8000000000000000LL);

    // Set exponent so it's in the [1.0-2.0] range
    // Check if 2.0 was selected
    if (*ExtendedConverter<sizeof(Extended)>::mPtr(&r12) == 0x8000000000000000LL)
        *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x4000;
    // otherwise, set the correct mantissa bit and the correct exponent
    else {
        // x87 extended format oddity: the first mantissa bit (always 1 for normal numbers) is visible, not hidden!
        // Since in this case this is a number between 1 and 2, this bit has to be set explicitly
        *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) |= 0x8000000000000000LL;
        *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x3FFF;
    }

    return r12;
}

// Random in 1..2 - need to exclude both bounds
template<> Extended Random12<false,false,Extended>(RandomState& state) {

    // Get uniform number between 1 and 2 at max precision

    // Work directly on Extended bits
    Extended r12;

    // Generate 63 bits for the mantissa
    do {
        *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) = Accessor<64>::getRandomInt(state);
        // x87 extended format oddity: the first mantissa bit (always 1 for normal numbers) is visible, not hidden!
        // Since in this case this is a number between 1 and 2, this bit has to be set explicitly
        *ExtendedConverter<sizeof(Extended)>::mPtr(&r12) |= 0x8000000000000000LL;
    }
    // Exclude both bounds : repeat the random get till it's in the desired range
    // Remove the possibility for 1.0 compared to all [1.0-2.0)
    while (*ExtendedConverter<sizeof(Extended)>::mPtr(&r12) == 0x8000000000000000LL);

    // Set exponent so it's in the (1.0-2.0) range
    *ExtendedConverter<sizeof(Extended)>::sexpPtr(&r12) = 0x3FFF;

    // scale from 1-2 interval to the desired interval
    return r12;
}

#endif

// This is a way to hide the implementation from the header
// And also to ensure there is only one template instanciation, instead of duplicating
// the code in all object files
template<typename FloatType> static inline FloatType NRandom_Generic(FloatType *secondary, RandomState& state) {

    FloatType x, y, d;
    // Generate a point strictly inside the unit circle
    do {
        // Use IE as this is the most convenient for the generation,
        // any will do since the bounds are rejected anyway by unit circle strict comparison
        x = RandomIE(FloatType(-1.0), FloatType(1.0), state);
        y = RandomIE(FloatType(-1.0), FloatType(1.0), state);
        d = x*x + y*y;
    } while (d>=FloatType(1.0));
    // Convert from x/y to uniform
    FloatType conv = sqrt( FloatType(-2.0) * log(d) / d );
    // Use one result as secondary independent variable, if user wishes
    if (secondary) *secondary = x * conv;
    // return the other
    return y * conv;
}

// Specialize for the Float types declared in the header
template<> Simple NRandom(Simple *secondary, RandomState& state) {
    return NRandom_Generic<Simple>(secondary,state);
}

/*
template<> Double NRandom(Double *secondary, RandomState& state) {
    return NRandom_Generic<Double>(secondary,state);
}
#if defined(Extended)
template<> Extended NRandom(Extended *secondary, RandomState& state) {
    return NRandom_Generic<Extended>(secondary,state);
}
#endif
*/

// May save one mul
template<typename FloatType> static inline FloatType NRandom_Generic(FloatType mean, FloatType std_dev, FloatType *secondary, RandomState& state) {

    FloatType x, y, d;
    // Generate a point strictly inside the unit circle
    do {
        // Use IE as this is the most convenient for the generation,
        // any will do since the bounds are rejected anyway by unit circle strict comparison
        x = RandomIE(FloatType(-1.0), FloatType(1.0), state);
        y = RandomIE(FloatType(-1.0), FloatType(1.0), state);
        d = x*x + y*y;
    } while (d>=FloatType(1.0));
    // Convert from x/y to uniform
    FloatType conv = sqrt( FloatType(-2.0) * log(d) / d ) * std_dev;
    // Use one result as secondary independent variable, if user wishes
    if (secondary) *secondary = x * conv + mean;
    // return the other
    return y * conv + mean;
}

// Specialize for the Float types declared in the header
template<> Simple NRandom(Simple mean, Simple std_dev, Simple *secondary, RandomState& state) {
    return NRandom_Generic<Simple>(mean, std_dev, secondary,state);
}

/*
template<> Double NRandom(Double mean, Double std_dev, Double *secondary, RandomState& state) {
    return NRandom_Generic<Double>(mean, std_dev, secondary,state);
}
#if defined(Extended)
template<> Extended NRandom(Extended mean, Extended std_dev, Extended *secondary, RandomState& state) {
    return NRandom_Generic<Extended>(mean, std_dev, secondary,state);
}
#endif
*/

SizedUnsignedInteger<32>::Type RandomInit(RandomState& state) {
    return RandomInit(SizedUnsignedInteger<32>::Type(time(0)));
}

SizedUnsignedInteger<32>::Type RandomInit(SizedUnsignedInteger<32>::Type seed, RandomState& state) {
    init_genrand(seed,state);
    return state.seed;
}

SizedUnsignedInteger<32>::Type RandomSeed(RandomState& state) {
    return state.seed;
}

// Default state holder, so single threaded applications don't bother setting up an object
RandomState DefaultRandomState;

} // end streflop namespace

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -