initial import

This commit is contained in:
kevin
2020-07-26 17:09:05 +08:00
commit 7e3a369a8f
647 changed files with 54754 additions and 0 deletions

14
core/mathx/entropy.go Normal file
View File

@@ -0,0 +1,14 @@
package mathx
import "math"
func CalcEntropy(m map[interface{}]int, total int) float64 {
var entropy float64
for _, v := range m {
proba := float64(v) / float64(total)
entropy -= proba * math.Log2(proba)
}
return entropy / math.Log2(float64(len(m)))
}

View File

@@ -0,0 +1,17 @@
package mathx
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCalcEntropy(t *testing.T) {
const total = 1000
const count = 100
m := make(map[interface{}]int, total)
for i := 0; i < total; i++ {
m[i] = count
}
assert.True(t, CalcEntropy(m, total*count) > .99)
}

17
core/mathx/int.go Normal file
View File

@@ -0,0 +1,17 @@
package mathx
func MaxInt(a, b int) int {
if a > b {
return a
} else {
return b
}
}
func MinInt(a, b int) int {
if a < b {
return a
} else {
return b
}
}

71
core/mathx/int_test.go Normal file
View File

@@ -0,0 +1,71 @@
package mathx
import (
"testing"
"zero/core/stringx"
"github.com/stretchr/testify/assert"
)
func TestMaxInt(t *testing.T) {
cases := []struct {
a int
b int
expect int
}{
{
a: 0,
b: 1,
expect: 1,
},
{
a: 0,
b: -1,
expect: 0,
},
{
a: 1,
b: 1,
expect: 1,
},
}
for _, each := range cases {
t.Run(stringx.Rand(), func(t *testing.T) {
actual := MaxInt(each.a, each.b)
assert.Equal(t, each.expect, actual)
})
}
}
func TestMinInt(t *testing.T) {
cases := []struct {
a int
b int
expect int
}{
{
a: 0,
b: 1,
expect: 0,
},
{
a: 0,
b: -1,
expect: -1,
},
{
a: 1,
b: 1,
expect: 1,
},
}
for _, each := range cases {
t.Run(stringx.Rand(), func(t *testing.T) {
actual := MinInt(each.a, each.b)
assert.Equal(t, each.expect, actual)
})
}
}

26
core/mathx/proba.go Normal file
View File

@@ -0,0 +1,26 @@
package mathx
import (
"math/rand"
"sync"
"time"
)
type Proba struct {
// rand.New(...) returns a non thread safe object
r *rand.Rand
lock sync.Mutex
}
func NewProba() *Proba {
return &Proba{
r: rand.New(rand.NewSource(time.Now().UnixNano())),
}
}
func (p *Proba) TrueOnProba(proba float64) (truth bool) {
p.lock.Lock()
truth = p.r.Float64() < proba
p.lock.Unlock()
return
}

24
core/mathx/proba_test.go Normal file
View File

@@ -0,0 +1,24 @@
package mathx
import (
"math"
"testing"
"github.com/stretchr/testify/assert"
)
func TestTrueOnProba(t *testing.T) {
const proba = math.Pi / 10
const total = 100000
const epsilon = 0.05
var count int
p := NewProba()
for i := 0; i < total; i++ {
if p.TrueOnProba(proba) {
count++
}
}
ratio := float64(count) / float64(total)
assert.InEpsilon(t, proba, ratio, epsilon)
}

41
core/mathx/unstable.go Normal file
View File

@@ -0,0 +1,41 @@
package mathx
import (
"math/rand"
"sync"
"time"
)
type Unstable struct {
deviation float64
r *rand.Rand
lock *sync.Mutex
}
func NewUnstable(deviation float64) Unstable {
if deviation < 0 {
deviation = 0
}
if deviation > 1 {
deviation = 1
}
return Unstable{
deviation: deviation,
r: rand.New(rand.NewSource(time.Now().UnixNano())),
lock: new(sync.Mutex),
}
}
func (u Unstable) AroundDuration(base time.Duration) time.Duration {
u.lock.Lock()
val := time.Duration((1 + u.deviation - 2*u.deviation*u.r.Float64()) * float64(base))
u.lock.Unlock()
return val
}
func (u Unstable) AroundInt(base int64) int64 {
u.lock.Lock()
val := int64((1 + u.deviation - 2*u.deviation*u.r.Float64()) * float64(base))
u.lock.Unlock()
return val
}

View File

@@ -0,0 +1,71 @@
package mathx
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestUnstable_AroundDuration(t *testing.T) {
unstable := NewUnstable(0.05)
for i := 0; i < 1000; i++ {
val := unstable.AroundDuration(time.Second)
assert.True(t, float64(time.Second)*0.95 <= float64(val))
assert.True(t, float64(val) <= float64(time.Second)*1.05)
}
}
func TestUnstable_AroundInt(t *testing.T) {
const target = 10000
unstable := NewUnstable(0.05)
for i := 0; i < 1000; i++ {
val := unstable.AroundInt(target)
assert.True(t, float64(target)*0.95 <= float64(val))
assert.True(t, float64(val) <= float64(target)*1.05)
}
}
func TestUnstable_AroundIntLarge(t *testing.T) {
const target int64 = 10000
unstable := NewUnstable(5)
for i := 0; i < 1000; i++ {
val := unstable.AroundInt(target)
assert.True(t, 0 <= val)
assert.True(t, val <= 2*target)
}
}
func TestUnstable_AroundIntNegative(t *testing.T) {
const target int64 = 10000
unstable := NewUnstable(-0.05)
for i := 0; i < 1000; i++ {
val := unstable.AroundInt(target)
assert.Equal(t, target, val)
}
}
func TestUnstable_Distribution(t *testing.T) {
const (
seconds = 10000
total = 10000
)
m := make(map[int]int)
expiry := NewUnstable(0.05)
for i := 0; i < total; i++ {
val := int(expiry.AroundInt(seconds))
m[val]++
}
_, ok := m[0]
assert.False(t, ok)
mi := make(map[interface{}]int, len(m))
for k, v := range m {
mi[k] = v
}
entropy := CalcEntropy(mi, total)
assert.True(t, len(m) > 1)
assert.True(t, entropy > 0.95)
}