Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
30
pkg/utils/mt19937/bernoulli_distribution.go
Normal file
30
pkg/utils/mt19937/bernoulli_distribution.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package mt19937
|
||||
|
||||
import (
|
||||
"fiskerinc.com/modules/logger"
|
||||
)
|
||||
|
||||
type bernoulli_distribution struct {
|
||||
m_prob float64
|
||||
m_eng *MT19937
|
||||
}
|
||||
|
||||
func DistBernolli(eng *MT19937, prob float64) *bernoulli_distribution {
|
||||
if prob < 0 || prob > 1 {
|
||||
logger.Error().Msg("prob must be between 0 and 1")
|
||||
return nil
|
||||
}
|
||||
dist := &bernoulli_distribution{
|
||||
m_prob: prob,
|
||||
m_eng: eng,
|
||||
}
|
||||
return dist
|
||||
}
|
||||
|
||||
func (dist *bernoulli_distribution) Bool() bool {
|
||||
if dist.m_prob == 0 {
|
||||
return false
|
||||
} else {
|
||||
return float64(dist.m_eng.Random()) <= dist.m_prob*float64(^uint64(0))
|
||||
}
|
||||
}
|
||||
81
pkg/utils/mt19937/discrete_distribution.go
Normal file
81
pkg/utils/mt19937/discrete_distribution.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package mt19937
|
||||
|
||||
import "fiskerinc.com/modules/logger"
|
||||
|
||||
type aliasTableUnit struct {
|
||||
weight float64
|
||||
index int
|
||||
}
|
||||
|
||||
type aliasTable struct {
|
||||
m_aliasTable []aliasTableUnit
|
||||
m_eng *MT19937
|
||||
}
|
||||
|
||||
func DistDiscrete(eng *MT19937, list []int) *aliasTable {
|
||||
if len(list) == 0 {
|
||||
logger.Error().Msg("list is not allowed empty!")
|
||||
return nil
|
||||
}
|
||||
var weightSum int
|
||||
for _, weight := range list {
|
||||
weightSum += weight
|
||||
}
|
||||
average := float64(weightSum) / float64(len(list))
|
||||
|
||||
table := &aliasTable{
|
||||
m_aliasTable: make([]aliasTableUnit, len(list)),
|
||||
m_eng: eng,
|
||||
}
|
||||
|
||||
below_average := make([]aliasTableUnit, 0, len(list))
|
||||
above_average := make([]aliasTableUnit, 0, len(list))
|
||||
|
||||
for i, weight := range list {
|
||||
val := float64(weight) / average
|
||||
unit := aliasTableUnit{
|
||||
weight: val,
|
||||
index: i,
|
||||
}
|
||||
if val < 1 {
|
||||
below_average = append(below_average, unit)
|
||||
} else {
|
||||
above_average = append(above_average, unit)
|
||||
}
|
||||
}
|
||||
|
||||
posA := 0
|
||||
posB := 0
|
||||
for posB < len(below_average) && posA < len(above_average) {
|
||||
table.m_aliasTable[below_average[posB].index] = aliasTableUnit{
|
||||
weight: below_average[posB].weight,
|
||||
index: above_average[posA].index,
|
||||
}
|
||||
above_average[posA].weight -= (1 - below_average[posB].weight)
|
||||
if above_average[posA].weight < 1 {
|
||||
below_average[posB] = above_average[posA]
|
||||
posA++
|
||||
} else {
|
||||
posB++
|
||||
}
|
||||
}
|
||||
|
||||
for ; posB < len(below_average); posB++ {
|
||||
table.m_aliasTable[below_average[posB].index].weight = float64(1)
|
||||
}
|
||||
for ; posA < len(above_average); posA++ {
|
||||
table.m_aliasTable[above_average[posA].index].weight = float64(1)
|
||||
}
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
func (dist *aliasTable) Discrete() int {
|
||||
result := int(DistInt64(dist.m_eng, 0, int64(len(dist.m_aliasTable)-1)).Int64())
|
||||
test := Dist01(dist.m_eng).Float64()
|
||||
if test < dist.m_aliasTable[result].weight {
|
||||
return result
|
||||
} else {
|
||||
return dist.m_aliasTable[result].index
|
||||
}
|
||||
}
|
||||
92
pkg/utils/mt19937/mt19937.go
Normal file
92
pkg/utils/mt19937/mt19937.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package mt19937
|
||||
|
||||
type MT19937 struct {
|
||||
state []uint64
|
||||
index int
|
||||
}
|
||||
|
||||
func New() *MT19937 {
|
||||
mt := &MT19937{
|
||||
state: make([]uint64, n),
|
||||
index: n,
|
||||
}
|
||||
mt.Seed(5489)
|
||||
return mt
|
||||
}
|
||||
|
||||
func (mt *MT19937) Seed(seed uint64) {
|
||||
x := mt.state
|
||||
x[0] = seed
|
||||
for i := 1; i < n; i++ {
|
||||
x[i] = f*(x[i-1]^(x[i-1]>>(w-2))) + uint64(i)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *MT19937) Random() uint64 {
|
||||
x := mt.state
|
||||
if mt.index == n {
|
||||
mt.twist()
|
||||
}
|
||||
var z uint64 = x[mt.index]
|
||||
|
||||
mt.index++
|
||||
|
||||
z ^= ((z >> u) & d)
|
||||
z ^= ((z << s) & b)
|
||||
z ^= ((z << t) & c)
|
||||
z ^= (z >> l)
|
||||
return z
|
||||
}
|
||||
|
||||
const (
|
||||
// The variables used in the algorithm are as follows:
|
||||
// w: length (in bits)
|
||||
// n: recursion length
|
||||
// m: period parameter, used as the offset of the third stage
|
||||
// r: low-order mask / low-order bits to be extracted
|
||||
// a: the parameters of the rotation matrix
|
||||
// b,c: TGFSR mask
|
||||
// s, t: the displacement of TGFSR
|
||||
// u,d,l: mask and displacement required for additional mason rotation
|
||||
// f: Initialize the required parameters of the Mason rotating chain
|
||||
|
||||
w = 64
|
||||
n = 312
|
||||
m = 156
|
||||
r = 31
|
||||
|
||||
a = 0xb5026f5aa96619e9
|
||||
|
||||
u = 29
|
||||
d = 0x5555555555555555
|
||||
|
||||
s = 17
|
||||
b = 0x71d67fffeda60000
|
||||
|
||||
t = 37
|
||||
c = 0xfff7eee000000000
|
||||
|
||||
l = 43
|
||||
|
||||
f = 6364136223846793005
|
||||
)
|
||||
|
||||
func (mt *MT19937) twist() {
|
||||
x := mt.state
|
||||
const lower_mask uint64 = 1<<r - 1
|
||||
const upper_mask uint64 = ^lower_mask
|
||||
|
||||
for j := 0; j < n-m; j++ {
|
||||
var y uint64 = (x[j] & upper_mask) | (x[j+1] & lower_mask)
|
||||
x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1] & 1) * a)
|
||||
}
|
||||
|
||||
for j := n - m; j < n-1; j++ {
|
||||
var y uint64 = (x[j] & upper_mask) | (x[j+1] & lower_mask)
|
||||
x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1] & 1) * a)
|
||||
}
|
||||
|
||||
var y uint64 = (x[n-1] & upper_mask) | (x[0] & lower_mask)
|
||||
x[n-1] = x[m-1] ^ (y >> 1) ^ ((x[0] & 1) * a)
|
||||
mt.index = 0
|
||||
}
|
||||
16
pkg/utils/mt19937/uniform_01.go
Normal file
16
pkg/utils/mt19937/uniform_01.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package mt19937
|
||||
|
||||
type uniform_01 struct {
|
||||
m_eng *MT19937
|
||||
}
|
||||
|
||||
func Dist01(eng *MT19937) *uniform_01 {
|
||||
dist := &uniform_01{
|
||||
m_eng: eng,
|
||||
}
|
||||
return dist
|
||||
}
|
||||
|
||||
func (dist *uniform_01) Float64() float64 {
|
||||
return float64(dist.m_eng.Random()) / float64(^uint64(0))
|
||||
}
|
||||
49
pkg/utils/mt19937/uniform_int_distribution.go
Normal file
49
pkg/utils/mt19937/uniform_int_distribution.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package mt19937
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
type UniformIntDistribution struct {
|
||||
m_min int64
|
||||
m_max int64
|
||||
m_eng *MT19937
|
||||
}
|
||||
|
||||
func DistInt64(eng *MT19937, begin int64, end int64) *UniformIntDistribution {
|
||||
if begin > end {
|
||||
log.Println("ERROR! begin is not allowed to be greater than end!")
|
||||
return nil
|
||||
}
|
||||
|
||||
dist := &UniformIntDistribution{
|
||||
m_min: begin,
|
||||
m_max: end,
|
||||
m_eng: eng,
|
||||
}
|
||||
return dist
|
||||
}
|
||||
|
||||
func (dist *UniformIntDistribution) Int64() int64 {
|
||||
var rng uint64
|
||||
|
||||
if dist.m_min >= 0 {
|
||||
rng = uint64(dist.m_max) - uint64(dist.m_min)
|
||||
} else if dist.m_max >= 0 {
|
||||
rng = uint64(dist.m_max) + uint64(-(dist.m_min + 1)) + 1
|
||||
} else {
|
||||
rng = uint64(dist.m_max - dist.m_min)
|
||||
}
|
||||
|
||||
if rng == 0 {
|
||||
return dist.m_min
|
||||
} else if rng == ^uint64(0) {
|
||||
return int64(dist.m_eng.Random())
|
||||
}
|
||||
bucket_size := ^uint64(0) / (rng + 1)
|
||||
if ^uint64(0)%(rng+1) == rng {
|
||||
bucket_size++
|
||||
}
|
||||
result := dist.m_eng.Random() / bucket_size
|
||||
return int64(result) + dist.m_min
|
||||
}
|
||||
Reference in New Issue
Block a user