github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/internal/mathutil/rand.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mathutil 16 17 import ( 18 "sync" 19 "time" 20 ) 21 22 const maxRandValue = 0x3FFFFFFF 23 24 // MysqlRng is random number generator and this implementation is ported from MySQL. 25 // See https://github.com/tikv/tikv/pull/6117#issuecomment-562489078. 26 type MysqlRng struct { 27 mu *sync.Mutex 28 seed1 uint32 29 seed2 uint32 30 } 31 32 // NewWithSeed create a rng with random seed. 33 func NewWithSeed(seed int64) *MysqlRng { 34 seed1 := uint32(seed*0x10001+55555555) % maxRandValue 35 seed2 := uint32(seed*0x10000001) % maxRandValue 36 return &MysqlRng{ 37 seed1: seed1, 38 seed2: seed2, 39 mu: &sync.Mutex{}, 40 } 41 } 42 43 // NewWithTime create a rng with time stamp. 44 func NewWithTime() *MysqlRng { 45 return NewWithSeed(time.Now().UnixNano()) 46 } 47 48 // Gen will generate random number. 49 func (rng *MysqlRng) Gen() float64 { 50 rng.mu.Lock() 51 defer rng.mu.Unlock() 52 rng.seed1 = (rng.seed1*3 + rng.seed2) % maxRandValue 53 rng.seed2 = (rng.seed1 + rng.seed2 + 33) % maxRandValue 54 return float64(rng.seed1) / float64(maxRandValue) 55 } 56 57 // SetSeed1 is a interface to set seed1 58 func (rng *MysqlRng) SetSeed1(seed uint32) { 59 rng.mu.Lock() 60 defer rng.mu.Unlock() 61 rng.seed1 = seed 62 } 63 64 // SetSeed2 is a interface to set seed2 65 func (rng *MysqlRng) SetSeed2(seed uint32) { 66 rng.mu.Lock() 67 defer rng.mu.Unlock() 68 rng.seed2 = seed 69 } 70 71 // GetSeed1 is an interface to get seed1. It's only used for getting session states. 72 func (rng *MysqlRng) GetSeed1() uint32 { 73 rng.mu.Lock() 74 defer rng.mu.Unlock() 75 return rng.seed1 76 } 77 78 // GetSeed2 is an interface to get seed2. It's only used for getting session states. 79 func (rng *MysqlRng) GetSeed2() uint32 { 80 rng.mu.Lock() 81 defer rng.mu.Unlock() 82 return rng.seed2 83 }