mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
parent
5eecd04eee
commit
3ed799ef7b
11 changed files with 208 additions and 34 deletions
|
@ -434,7 +434,7 @@ pub fn covariance_mean[T](data1 []T, data2 []T, mean1 T, mean2 T) T {
|
|||
for i in 0 .. n {
|
||||
delta1 := data1[i] - mean1
|
||||
delta2 := data2[i] - mean2
|
||||
covariance += T((delta1 * delta2 - covariance) / (i + T(1)))
|
||||
covariance += T((delta1 * delta2 - covariance) / (T(i) + T(1)))
|
||||
}
|
||||
return covariance
|
||||
}
|
||||
|
@ -459,8 +459,11 @@ pub fn lag1_autocorrelation_mean[T](data []T, mean T) T {
|
|||
for i := 1; i < data.len; i++ {
|
||||
delta0 := data[i - 1] - mean
|
||||
delta1 := data[i] - mean
|
||||
q += T((delta0 * delta1 - q) / (i + T(1)))
|
||||
v += T((delta1 * delta1 - v) / (T(i) + T(1)))
|
||||
d01 := delta0 * delta1
|
||||
d11 := delta1 * delta1
|
||||
ti1 := T(i) + T(1)
|
||||
q += T((d01 - q) / ti1)
|
||||
v += T((d11 - v) / ti1)
|
||||
}
|
||||
return T(q / v)
|
||||
}
|
||||
|
@ -486,7 +489,9 @@ pub fn kurtosis_mean_stddev[T](data []T, mean T, sd T) T {
|
|||
*/
|
||||
for i, v in data {
|
||||
x := (v - mean) / sd
|
||||
avg += T((x * x * x * x - avg) / (i + T(1)))
|
||||
x4 := x * x * x * x
|
||||
ti1 := (T(i) + T(1))
|
||||
avg += T((x4 - avg) / ti1)
|
||||
}
|
||||
return avg - T(3)
|
||||
}
|
||||
|
@ -511,7 +516,8 @@ pub fn skew_mean_stddev[T](data []T, mean T, sd T) T {
|
|||
*/
|
||||
for i, v in data {
|
||||
x := (v - mean) / sd
|
||||
skew += T((x * x * x - skew) / (i + T(1)))
|
||||
x3 := x * x * x
|
||||
skew += T((x3 - skew) / (T(i) + T(1)))
|
||||
}
|
||||
return skew
|
||||
}
|
||||
|
|
|
@ -400,15 +400,15 @@ fn test_covariance() {
|
|||
mut data0 := [10.0, 4.45, 5.9, 2.7]
|
||||
mut data1 := [5.0, 14.45, -15.9, 22.7]
|
||||
mut o := stats.covariance(data0, data1)
|
||||
assert math.alike(o, -17.37078207731247)
|
||||
assert math.alike(o, -17.37078125)
|
||||
data0 = [-3.0, 67.31, 4.4, 1.89]
|
||||
data1 = [5.0, 77.31, 44.4, 11.89]
|
||||
o = stats.covariance(data0, data1)
|
||||
assert math.alike(o, 740.0695419311523)
|
||||
assert math.alike(o, 740.06955)
|
||||
data0 = [12.0, 7.88, 76.122, 54.83]
|
||||
data1 = [2.0, 5.88, 7.122, 5.83]
|
||||
o = stats.covariance(data0, data1)
|
||||
assert math.alike(o, 36.65028190612793)
|
||||
assert math.alike(o, 36.650282000000004)
|
||||
|
||||
// test for int, i64, f32 array
|
||||
data0_int := [1, 2, 3, 1]
|
||||
|
@ -428,13 +428,15 @@ fn test_covariance() {
|
|||
fn test_lag1_autocorrelation() {
|
||||
mut data := [10.0, 4.45, 5.9, 2.7]
|
||||
mut o := stats.lag1_autocorrelation(data)
|
||||
assert math.alike(o, -0.554228566606572)
|
||||
mut e := 0.0
|
||||
assert math.alike(o, -0.5542285481446095)
|
||||
data = [-3.0, 67.31, 4.4, 1.89]
|
||||
o = stats.lag1_autocorrelation(data)
|
||||
assert math.alike(o, -0.5102510823460722)
|
||||
assert math.alike(o, -0.5102510654033415)
|
||||
data = [12.0, 7.88, 76.122, 54.83]
|
||||
o = stats.lag1_autocorrelation(data)
|
||||
assert math.alike(o, 0.10484451825170164)
|
||||
e = 0.10484450460892072
|
||||
assert math.alike(o, e), diff(o, e)
|
||||
|
||||
// test for int, i64, f32 array
|
||||
assert stats.lag1_autocorrelation[int]([1, 2, 3, 1]) == 0
|
||||
|
@ -443,40 +445,51 @@ fn test_lag1_autocorrelation() {
|
|||
assert math.alike(o, 0.1975308507680893)
|
||||
}
|
||||
|
||||
fn diff(actual f64, expected f64) string {
|
||||
return '\n actual:${actual:40.35f}\nexpected:${expected:40.35f}\n diff:${actual - expected:40.35f}'
|
||||
}
|
||||
|
||||
fn test_kurtosis() {
|
||||
mut data := [10.0, 4.45, 5.9, 2.7]
|
||||
mut o := stats.kurtosis(data)
|
||||
assert math.alike(o, -1.0443214689384779)
|
||||
mut e := -1.0443212849233845
|
||||
assert math.close(o, e), diff(o, e)
|
||||
data = [-3.0, 67.31, 4.4, 1.89]
|
||||
o = stats.kurtosis(data)
|
||||
assert math.alike(o, -0.688495594786176)
|
||||
e = -0.6884953374814851
|
||||
assert math.close(o, e), diff(o, e)
|
||||
data = [12.0, 7.88, 76.122, 54.83]
|
||||
o = stats.kurtosis(data)
|
||||
assert math.alike(o, -1.7323772574195067)
|
||||
assert math.alike(o, -1.7323772836921467)
|
||||
|
||||
// test for int, i64, f32 array
|
||||
assert stats.kurtosis[int]([1, 2, 3, 1]) == 1
|
||||
assert stats.kurtosis[i64]([i64(1), 2, 3, 1]) == 1
|
||||
o = stats.kurtosis[f32]([f32(1.0), 3, 5, 7, 3])
|
||||
assert math.alike(o, -1.0443782806396484)
|
||||
e = -1.044378399848938
|
||||
assert math.alike(o, e), diff(o, e)
|
||||
}
|
||||
|
||||
fn test_skew() {
|
||||
mut data := [10.0, 4.45, 5.9, 2.7]
|
||||
mut o := stats.skew(data)
|
||||
assert math.alike(o, 0.5754020379048158)
|
||||
mut e := 0.5754021106320453
|
||||
assert math.veryclose(o, e), diff(o, e)
|
||||
data = [-3.0, 67.31, 4.4, 1.89]
|
||||
o = stats.skew(data)
|
||||
assert math.alike(o, 1.1248732608899568)
|
||||
e = 1.1248733711136492
|
||||
assert math.veryclose(o, e), diff(o, e)
|
||||
data = [12.0, 7.88, 76.122, 54.83]
|
||||
o = stats.skew(data)
|
||||
assert math.alike(o, 0.19007917421924964)
|
||||
e = 0.19007911706827735
|
||||
assert math.alike(o, e), diff(o, e)
|
||||
|
||||
// test for int, i64, f32 array
|
||||
assert stats.skew[int]([1, 2, 3, 1]) == 2
|
||||
assert stats.skew[i64]([i64(1), 2, 3, 1]) == 2
|
||||
o = stats.skew[f32]([f32(1.0), 3, 5, 7, 3])
|
||||
assert math.alike(o, 0.2715454697608948)
|
||||
e = 0.27154541015625
|
||||
assert math.alike(o, e), diff(o, e)
|
||||
}
|
||||
|
||||
fn test_quantile() {
|
||||
|
@ -484,13 +497,13 @@ fn test_quantile() {
|
|||
|
||||
mut data := [2.7, 4.45, 5.9, 10.0]
|
||||
mut o := stats.quantile(data, 0.1)!
|
||||
assert math.alike(o, 3.225000020861626)
|
||||
assert math.alike(o, 3.225)
|
||||
data = [-3.0, 1.89, 4.4, 67.31]
|
||||
o = stats.quantile(data, 0.2)!
|
||||
assert math.alike(o, -0.06599988341331486)
|
||||
assert math.alike(o, -0.06599999999999961)
|
||||
data = [7.88, 12.0, 54.83, 76.122]
|
||||
o = stats.quantile(data, 0.3)!
|
||||
assert math.alike(o, 11.587999901771546)
|
||||
assert math.alike(o, 11.588)
|
||||
|
||||
stats.quantile(data, -0.3) or { assert err.msg() == 'index out of range' }
|
||||
|
||||
|
|
|
@ -43,6 +43,22 @@ const dec_round = [
|
|||
0.000000000000000005,
|
||||
0.0000000000000000005,
|
||||
0.00000000000000000005,
|
||||
0.000000000000000000005,
|
||||
0.0000000000000000000005,
|
||||
0.00000000000000000000005,
|
||||
0.000000000000000000000005,
|
||||
0.0000000000000000000000005,
|
||||
0.00000000000000000000000005,
|
||||
0.000000000000000000000000005,
|
||||
0.0000000000000000000000000005,
|
||||
0.00000000000000000000000000005,
|
||||
0.000000000000000000000000000005,
|
||||
0.0000000000000000000000000000005,
|
||||
0.00000000000000000000000000000005,
|
||||
0.000000000000000000000000000000005,
|
||||
0.0000000000000000000000000000000005,
|
||||
0.00000000000000000000000000000000005,
|
||||
0.000000000000000000000000000000000005,
|
||||
]!
|
||||
|
||||
// Single format functions
|
||||
|
|
|
@ -209,7 +209,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
|
|||
|
||||
// allocate exp+32 chars for the return string
|
||||
// mut res := []u8{len:exp+32,init:`0`}
|
||||
mut res := []u8{len: exp + 32, init: 0}
|
||||
mut res := []u8{len: exp + 40, init: 0}
|
||||
mut r_i := 0 // result string buffer index
|
||||
|
||||
// println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
|
||||
|
|
|
@ -23,6 +23,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
node.left_types = []
|
||||
mut right_len := node.right.len
|
||||
mut right_first_type := ast.void_type
|
||||
old_recheck := c.inside_recheck
|
||||
// check if we are rechecking an already checked expression on generic rechecking
|
||||
c.inside_recheck = old_recheck || node.right_types.len > 0
|
||||
defer {
|
||||
c.inside_recheck = old_recheck
|
||||
}
|
||||
for i, mut right in node.right {
|
||||
if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr,
|
||||
ast.SelectorExpr, ast.ParExpr, ast.ComptimeCall] {
|
||||
|
@ -37,7 +43,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
}
|
||||
right_type_sym := c.table.sym(right_type)
|
||||
// fixed array returns an struct, but when assigning it must be the array type
|
||||
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
|
||||
if right_type_sym.info is ast.ArrayFixed {
|
||||
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
|
||||
}
|
||||
if i == 0 {
|
||||
right_first_type = right_type
|
||||
node.right_types = [
|
||||
|
@ -62,11 +70,23 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if mut right is ast.InfixExpr {
|
||||
} else if mut right is ast.InfixExpr {
|
||||
if right.op == .arrow {
|
||||
c.error('cannot use `<-` on the right-hand side of an assignment, as it does not return any values',
|
||||
right.pos)
|
||||
} else if c.inside_recheck {
|
||||
mut right_type := c.expr(mut right)
|
||||
right_type_sym := c.table.sym(right_type)
|
||||
// fixed array returns an struct, but when assigning it must be the array type
|
||||
if right_type_sym.info is ast.ArrayFixed {
|
||||
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
|
||||
}
|
||||
if i == 0 {
|
||||
right_first_type = right_type
|
||||
node.right_types = [
|
||||
c.check_expr_option_or_result_call(right, right_first_type),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
if mut right is ast.Ident {
|
||||
|
@ -182,16 +202,13 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
node.right_types << c.check_expr_option_or_result_call(node.right[i],
|
||||
right_type)
|
||||
}
|
||||
} else {
|
||||
} else if c.inside_recheck {
|
||||
// on generic recheck phase it might be needed to resolve the rhs again
|
||||
if i < node.right.len && c.comptime.has_comptime_expr(node.right[i]) {
|
||||
mut expr := mut node.right[i]
|
||||
old_inside_recheck := c.inside_recheck
|
||||
c.inside_recheck = true
|
||||
right_type := c.expr(mut expr)
|
||||
node.right_types[i] = c.check_expr_option_or_result_call(node.right[i],
|
||||
right_type)
|
||||
c.inside_recheck = old_inside_recheck
|
||||
}
|
||||
}
|
||||
mut right := if i < node.right.len { node.right[i] } else { node.right[0] }
|
||||
|
@ -393,6 +410,17 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
left.obj.ct_type_var = .field_var
|
||||
left.obj.typ = c.comptime.comptime_for_field_type
|
||||
}
|
||||
} else if mut right is ast.InfixExpr {
|
||||
right_ct_var := c.comptime.get_ct_type_var(right.left)
|
||||
if right_ct_var != .no_comptime {
|
||||
left.obj.ct_type_var = right_ct_var
|
||||
}
|
||||
} else if mut right is ast.IndexExpr
|
||||
&& c.comptime.is_comptime(right) {
|
||||
right_ct_var := c.comptime.get_ct_type_var(right.left)
|
||||
if right_ct_var != .no_comptime {
|
||||
left.obj.ct_type_var = right_ct_var
|
||||
}
|
||||
} else if mut right is ast.Ident && right.obj is ast.Var
|
||||
&& right.or_expr.kind == .absent {
|
||||
right_obj_var := right.obj as ast.Var
|
||||
|
|
|
@ -371,6 +371,19 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||
left.obj.typ = var_type
|
||||
g.assign_ct_type = var_type
|
||||
}
|
||||
} else if val is ast.InfixExpr && val.op in [.plus, .minus, .mul, .div, .mod]
|
||||
&& g.comptime.is_comptime(val.left) {
|
||||
ctyp := g.unwrap_generic(g.type_resolver.get_type(val.left))
|
||||
if ctyp != ast.void_type {
|
||||
ct_type_var := g.comptime.get_ct_type_var(val.left)
|
||||
if ct_type_var in [.key_var, .value_var] {
|
||||
g.type_resolver.update_ct_type(left.name, g.unwrap_generic(ctyp))
|
||||
}
|
||||
var_type = ctyp
|
||||
val_type = var_type
|
||||
left.obj.typ = var_type
|
||||
g.assign_ct_type = var_type
|
||||
}
|
||||
}
|
||||
is_auto_heap = left.obj.is_auto_heap
|
||||
}
|
||||
|
|
|
@ -1188,8 +1188,10 @@ fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) {
|
|||
&& node.op in [.plus, .minus, .mul, .div, .mod] && !(g.pref.translated
|
||||
|| g.file.is_translated)
|
||||
if needs_cast {
|
||||
typ_str := if g.comptime.is_comptime(node.left) {
|
||||
typ_str := if !node.left.is_literal() && g.comptime.is_comptime(node.left) {
|
||||
g.styp(g.type_resolver.get_type_or_default(node.left, node.promoted_type))
|
||||
} else if !node.right.is_literal() && g.comptime.is_comptime(node.right) {
|
||||
g.styp(g.type_resolver.get_type_or_default(node.right, node.promoted_type))
|
||||
} else {
|
||||
g.styp(node.promoted_type)
|
||||
}
|
||||
|
|
62
vlib/v/tests/comptime/comptime_infix_assign_test.v
Normal file
62
vlib/v/tests/comptime/comptime_infix_assign_test.v
Normal file
|
@ -0,0 +1,62 @@
|
|||
enum Flag {
|
||||
usa_old_glory
|
||||
all_other_bad_excuses_for_a_flag
|
||||
}
|
||||
|
||||
struct Test {
|
||||
is_foo bool
|
||||
name [5]u8
|
||||
}
|
||||
|
||||
fn enc[T](item T) string {
|
||||
$if T is $int {
|
||||
len := match typeof(item).name {
|
||||
'i8', 'u8' { u8(2) }
|
||||
'i16', 'u16' { 4 }
|
||||
'int', 'u32', 'i32' { 8 }
|
||||
'i64', 'u64' { 16 }
|
||||
else { return '' }
|
||||
}
|
||||
return u64_to_hex(item, len)
|
||||
} $else $if T is $array {
|
||||
mut hex := ''
|
||||
for val in item {
|
||||
hex += enc(val)
|
||||
}
|
||||
return hex
|
||||
} $else $if T is $struct {
|
||||
mut hex := ''
|
||||
$for field in T.fields {
|
||||
hex += enc(item.$(field.name)) + '_'
|
||||
}
|
||||
return hex
|
||||
} $else {
|
||||
if typeof(item).name == 'bool' {
|
||||
return enc(int(item))
|
||||
}
|
||||
$if debug {
|
||||
println('cannot encode ${T}(s)')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
@[direct_array_access; inline]
|
||||
fn u64_to_hex(nn u64, len u8) string {
|
||||
mut n := nn
|
||||
mut buf := [17]u8{}
|
||||
buf[len] = 0
|
||||
mut i := 0
|
||||
for i = len - 1; i >= 0; i-- {
|
||||
d := u8(n & 0xF)
|
||||
buf[i] = if d < 10 { d + `0` } else { d + 87 }
|
||||
n = n >> 4
|
||||
}
|
||||
return unsafe { tos(memdup(&buf[0], len + 1), len) }
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
assert enc(Test{}) == '00000000_0000000000_'
|
||||
assert enc(Test{ is_foo: true }) == '00000001_0000000000_'
|
||||
assert enc(Test{ name: [u8(1), 2, 3, 4, 5]! }) == '00000000_0102030405_'
|
||||
}
|
|
@ -50,7 +50,11 @@ pub fn (t &ResolverInfo) is_comptime(node ast.Expr) bool {
|
|||
return node.expr is ast.Ident && node.expr.ct_expr
|
||||
}
|
||||
ast.InfixExpr {
|
||||
return t.is_comptime(node.left) || t.is_comptime(node.right)
|
||||
if node.op in [.plus, .minus, .mul, .div, .mod] {
|
||||
t.is_comptime(node.left) || t.is_comptime(node.right)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
ast.ParExpr {
|
||||
return t.is_comptime(node.expr)
|
||||
|
@ -76,6 +80,10 @@ pub fn (t &ResolverInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind {
|
|||
}
|
||||
} else if node is ast.IndexExpr {
|
||||
return t.get_ct_type_var(node.left)
|
||||
} else if node is ast.InfixExpr {
|
||||
return t.get_ct_type_var(node.left)
|
||||
} else if node is ast.ParExpr {
|
||||
return t.get_ct_type_var(node.expr)
|
||||
}
|
||||
return .no_comptime
|
||||
}
|
||||
|
|
|
@ -297,7 +297,7 @@ pub fn (mut t TypeResolver) resolve_args(cur_fn &ast.FnDecl, func &ast.Fn, mut n
|
|||
comptime_args[k] = m.return_type
|
||||
}
|
||||
}
|
||||
} else if mut call_arg.expr is ast.CastExpr {
|
||||
} else if mut call_arg.expr is ast.CastExpr && call_arg.expr.typ.has_flag(.generic) {
|
||||
cparam_type_sym := t.table.sym(t.resolver.unwrap_generic(call_arg.expr.typ))
|
||||
param_typ_sym := t.table.sym(param_typ)
|
||||
if param_typ_sym.kind == .map && cparam_type_sym.info is ast.Map {
|
||||
|
|
|
@ -115,9 +115,25 @@ pub fn (mut t TypeResolver) get_type_or_default(node ast.Expr, default_typ ast.T
|
|||
return t.get_type_or_default(node.expr, default_typ)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
if node.op in [.plus, .minus, .mul, .div, .mod] {
|
||||
if !node.left.is_literal() && node.op in [.plus, .minus, .mul, .div, .mod] {
|
||||
return t.get_type_or_default(node.left, default_typ)
|
||||
}
|
||||
if !node.right.is_literal() && node.op in [.plus, .minus, .mul, .div, .mod] {
|
||||
return t.get_type_or_default(node.right, default_typ)
|
||||
}
|
||||
}
|
||||
ast.IndexExpr {
|
||||
if node.left is ast.Ident && node.left.ct_expr {
|
||||
ctyp := t.get_type(node)
|
||||
if ctyp != ast.void_type {
|
||||
return ctyp
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.CastExpr {
|
||||
if node.typ.has_flag(.generic) {
|
||||
return t.resolver.unwrap_generic(node.typ)
|
||||
}
|
||||
}
|
||||
else {
|
||||
return default_typ
|
||||
|
@ -184,6 +200,16 @@ pub fn (mut t TypeResolver) get_type(node ast.Expr) ast.Type {
|
|||
nltype := t.get_type(node.left)
|
||||
nltype_unwrapped := t.resolver.unwrap_generic(nltype)
|
||||
return t.table.value_type(nltype_unwrapped)
|
||||
} else if node is ast.ParExpr && t.info.is_comptime(node.expr) {
|
||||
return t.get_type(node.expr)
|
||||
} else if node is ast.InfixExpr {
|
||||
if !node.left.is_literal() && t.info.is_comptime(node.left) {
|
||||
return t.get_type(node.left)
|
||||
} else if !node.right.is_literal() && t.info.is_comptime(node.right) {
|
||||
return t.get_type(node.right)
|
||||
}
|
||||
} else if node is ast.CastExpr && node.typ.has_flag(.generic) {
|
||||
return t.resolver.unwrap_generic(node.typ)
|
||||
}
|
||||
return ast.void_type
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue