Source File
random.go
Belonging Package
github.com/d2lang/elk-go/internal/javacompat
// Copyright (c) 2026 The elk-go Authors.//// This program and the accompanying materials are made available under the// terms of the Eclipse Public License 2.0 which is available at// https://www.eclipse.org/legal/epl-2.0.//// SPDX-License-Identifier: EPL-2.0// Package javacompat contains the small parts of the Java runtime whose exact// behavior is observable in ELK layouts.package javacompatimportconst (randomMultiplier uint64 = 0x5DEECE66DrandomAddend uint64 = 0xBrandomMask uint64 = (1 << 48) - 1)// Random is a bit-for-bit implementation of java.util.Random from Java 8.//// Random is not safe for concurrent use. ELK owns one instance per layout, as// the Java implementation does, so synchronization would only obscure the// order in which random values are consumed.type Random struct {seed uint64haveNextGaussian boolnextGaussian float64}// NewRandom constructs a Java-compatible pseudo-random number generator.func ( int64) *Random {:= &Random{}.SetSeed()return}// SetSeed implements Random.setSeed(long). It also clears the cached value// used by NextGaussian.func ( *Random) ( int64) {.seed = (uint64() ^ randomMultiplier) & randomMask.haveNextGaussian = false}// next implements Random.next(int). Only Java's public Random methods should// call it; the valid range is 1..32.func ( *Random) ( uint) int32 {if == 0 || > 32 {panic("javacompat.Random.next: bits must be in [1, 32]")}.seed = (.seed*randomMultiplier + randomAddend) & randomMaskreturn int32(.seed >> (48 - ))}// NextInt implements Random.nextInt().func ( *Random) () int32 {return .next(32)}// NextIntN implements Random.nextInt(bound). It panics for a non-positive// bound, corresponding to Java's IllegalArgumentException.func ( *Random) ( int32) int32 {if <= 0 {panic("javacompat.Random.NextIntN: bound must be positive")}if &- == {return int32((int64() * int64(.next(31))) >> 31)}for {:= .next(31):= %// The expression deliberately has int32 overflow semantics. Java uses// the overflow to reject the small biased tail of the 31-bit range.if -+(-1) >= 0 {return}}}// NextLong implements Random.nextLong(). The low 32 bits are sign-extended// before addition, as required by Java's two signed int32 draws.func ( *Random) () int64 {return (int64(.next(32)) << 32) + int64(.next(32))}// NextBoolean implements Random.nextBoolean().func ( *Random) () bool {return .next(1) != 0}// NextFloat implements Random.nextFloat().func ( *Random) () float32 {return float32(.next(24)) / float32(1<<24)}// NextDouble implements Random.nextDouble().func ( *Random) () float64 {:= int64(.next(26)) << 27:= int64(.next(27))return float64(+) / float64(int64(1)<<53)}// NextBytes implements Random.nextBytes(byte[]). Java's byte is signed, but// assigning its low eight bits to a Go byte gives the same byte sequence.func ( *Random) ( []byte) {for := 0; < len(); {:= .NextInt():= len() -if > 4 {= 4}for ; > 0; -- {[] = byte()++>>= 8}}}// NextGaussian implements Random.nextGaussian(), including its cached second// sample. ELK 0.8.1 does not use this in a layout path, but providing the Java// behavior prevents consumers from accidentally substituting math/rand.// Math-library results may differ by a final bit across platforms, just as// Java's Math implementation may, while the random-value consumption is exact.func ( *Random) () float64 {if .haveNextGaussian {.haveNextGaussian = falsereturn .nextGaussian}for {:= 2*.NextDouble() - 1:= 2*.NextDouble() - 1:= * + *if >= 1 || == 0 {continue}:= math.Sqrt(-2 * math.Log() / ).nextGaussian = *.haveNextGaussian = truereturn *}}
![]() |
The pages are generated with Golds v0.8.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |