view src/testdir/test_float_func.vim @ 34074:1629cc65d78d v9.1.0006

patch 9.1.0006: is*() and to*() function may be unsafe Commit: https://github.com/vim/vim/commit/184f71cc6868a240dc872ed2852542bbc1d43e28 Author: Keith Thompson <Keith.S.Thompson@gmail.com> Date: Thu Jan 4 21:19:04 2024 +0100 patch 9.1.0006: is*() and to*() function may be unsafe Problem: is*() and to*() function may be unsafe Solution: Add SAFE_* macros and start using those instead (Keith Thompson) Use SAFE_() macros for is*() and to*() functions The standard is*() and to*() functions declared in <ctype.h> have undefined behavior for negative arguments other than EOF. If plain char is signed, passing an unchecked value from argv for from user input to one of these functions has undefined behavior. Solution: Add SAFE_*() macros that cast the argument to unsigned char. Most implementations behave sanely for negative arguments, and most character values in practice are non-negative, but it's still best to avoid undefined behavior. The change from #13347 has been omitted, as this has already been separately fixed in commit ac709e2fc0db6d31abb7da96f743c40956b60c3a (v9.0.2054) fixes: #13332 closes: #13347 Signed-off-by: Keith Thompson <Keith.S.Thompson@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 04 Jan 2024 21:30:04 +0100
parents 029c59bf78f1
children
line wrap: on
line source

" test float functions

source check.vim
import './vim9.vim' as v9

func Test_abs()
  call assert_equal('1.23', string(abs(1.23)))
  call assert_equal('1.23', string(abs(-1.23)))
  eval -1.23->abs()->string()->assert_equal('1.23')

  call assert_equal('0.0', string(abs(0.0)))
  call assert_equal('0.0', string(abs(1.0/(1.0/0.0))))
  call assert_equal('0.0', string(abs(-1.0/(1.0/0.0))))
  call assert_equal('inf', string(abs(1.0/0.0)))
  call assert_equal('inf', string(abs(-1.0/0.0)))
  call assert_equal('nan', string(abs(0.0/0.0)))
  call assert_equal('12', string(abs('12abc')))
  call assert_equal('12', string(abs('-12abc')))
  call assert_fails("call abs([])", 'E745:')
  call assert_fails("call abs({})", 'E728:')
  call assert_fails("call abs(function('string'))", 'E703:')
endfunc

func Test_sqrt()
  call assert_equal('0.0', string(sqrt(0.0)))
  call assert_equal('1.414214', string(sqrt(2.0)))
  eval 2.0->sqrt()->string()->assert_equal('1.414214')
  call assert_equal('inf', string(sqrt(1.0/0.0)))
  call assert_equal('nan', string(sqrt(-1.0)))
  call assert_equal('nan', string(sqrt(0.0/0.0)))
  call assert_fails('call sqrt("")', 'E808:')
endfunc

func Test_log()
  call assert_equal('0.0', string(log(1.0)))
  call assert_equal('-0.693147', string(log(0.5)))
  eval 0.5->log()->string()->assert_equal('-0.693147')
  call assert_equal('-inf', string(log(0.0)))
  call assert_equal('nan', string(log(-1.0)))
  call assert_equal('inf', string(log(1.0/0.0)))
  call assert_equal('nan', string(log(0.0/0.0)))
  call assert_fails('call log("")', 'E808:')
endfunc

func Test_log10()
  call assert_equal('0.0', string(log10(1.0)))
  call assert_equal('2.0', string(log10(100.0)))
  call assert_equal('2.079181', string(log10(120.0)))
  eval 120.0->log10()->string()->assert_equal('2.079181')
  call assert_equal('-inf', string(log10(0.0)))
  call assert_equal('nan', string(log10(-1.0)))
  call assert_equal('inf', string(log10(1.0/0.0)))
  call assert_equal('nan', string(log10(0.0/0.0)))
  call assert_fails('call log10("")', 'E808:')
endfunc

func Test_exp()
  call assert_equal('1.0', string(exp(0.0)))
  call assert_equal('7.389056', string(exp(2.0)))
  call assert_equal('0.367879', string(exp(-1.0)))
  eval -1.0->exp()->string()->assert_equal('0.367879')
  call assert_equal('inf', string(exp(1.0/0.0)))
  call assert_equal('0.0', string(exp(-1.0/0.0)))
  call assert_equal('nan', string(exp(0.0/0.0)))
  call assert_fails('call exp("")', 'E808:')
endfunc

func Test_sin()
  call assert_equal('0.0', string(sin(0.0)))
  call assert_equal('0.841471', string(sin(1.0)))
  call assert_equal('-0.479426', string(sin(-0.5)))
  eval -0.5->sin()->string()->assert_equal('-0.479426')
  call assert_equal('nan', string(sin(0.0/0.0)))
  call assert_equal('nan', string(sin(1.0/0.0)))
  call assert_equal('0.0', string(sin(1.0/(1.0/0.0))))
  call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0))))
  call assert_fails('call sin("")', 'E808:')
endfunc

func Test_asin()
  call assert_equal('0.0', string(asin(0.0)))
  call assert_equal('1.570796', string(asin(1.0)))
  eval 1.0->asin()->string()->assert_equal('1.570796')

  call assert_equal('-0.523599', string(asin(-0.5)))
  call assert_equal('nan', string(asin(1.1)))
  call assert_equal('nan', string(asin(1.0/0.0)))
  call assert_equal('nan', string(asin(0.0/0.0)))
  call assert_fails('call asin("")', 'E808:')
endfunc

func Test_sinh()
  call assert_equal('0.0', string(sinh(0.0)))
  call assert_equal('0.521095', string(sinh(0.5)))
  call assert_equal('-1.026517', string(sinh(-0.9)))
  eval -0.9->sinh()->string()->assert_equal('-1.026517')
  call assert_equal('inf', string(sinh(1.0/0.0)))
  call assert_equal('-inf', string(sinh(-1.0/0.0)))
  call assert_equal('nan', string(sinh(0.0/0.0)))
  call assert_fails('call sinh("")', 'E808:')
endfunc

func Test_cos()
  call assert_equal('1.0', string(cos(0.0)))
  call assert_equal('0.540302', string(cos(1.0)))
  call assert_equal('0.877583', string(cos(-0.5)))
  eval -0.5->cos()->string()->assert_equal('0.877583')
  call assert_equal('nan', string(cos(0.0/0.0)))
  call assert_equal('nan', string(cos(1.0/0.0)))
  call assert_fails('call cos("")', 'E808:')
endfunc

func Test_acos()
  call assert_equal('1.570796', string(acos(0.0)))
  call assert_equal('0.0', string(acos(1.0)))
  call assert_equal('3.141593', string(acos(-1.0)))
  eval -1.0->acos()->string()->assert_equal('3.141593')
  call assert_equal('2.094395', string(acos(-0.5)))
  call assert_equal('nan', string(acos(1.1)))
  call assert_equal('nan', string(acos(1.0/0.0)))
  call assert_equal('nan', string(acos(0.0/0.0)))
  call assert_fails('call acos("")', 'E808:')
endfunc

func Test_cosh()
  call assert_equal('1.0', string(cosh(0.0)))
  call assert_equal('1.127626', string(cosh(0.5)))
  eval 0.5->cosh()->string()->assert_equal('1.127626')
  call assert_equal('inf', string(cosh(1.0/0.0)))
  call assert_equal('inf', string(cosh(-1.0/0.0)))
  call assert_equal('nan', string(cosh(0.0/0.0)))
  call assert_fails('call cosh("")', 'E808:')
endfunc

func Test_tan()
  call assert_equal('0.0', string(tan(0.0)))
  call assert_equal('0.546302', string(tan(0.5)))
  call assert_equal('-0.546302', string(tan(-0.5)))
  eval -0.5->tan()->string()->assert_equal('-0.546302')
  call assert_equal('nan', string(tan(1.0/0.0)))
  call assert_equal('nan', string(cos(0.0/0.0)))
  call assert_equal('0.0', string(tan(1.0/(1.0/0.0))))
  call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0))))
  call assert_fails('call tan("")', 'E808:')
endfunc

func Test_atan()
  call assert_equal('0.0', string(atan(0.0)))
  call assert_equal('0.463648', string(atan(0.5)))
  call assert_equal('-0.785398', string(atan(-1.0)))
  eval -1.0->atan()->string()->assert_equal('-0.785398')
  call assert_equal('1.570796', string(atan(1.0/0.0)))
  call assert_equal('-1.570796', string(atan(-1.0/0.0)))
  call assert_equal('nan', string(atan(0.0/0.0)))
  call assert_fails('call atan("")', 'E808:')
endfunc

func Test_atan2()
  call assert_equal('-2.356194', string(atan2(-1, -1)))
  call assert_equal('2.356194', string(atan2(1, -1)))
  call assert_equal('0.0', string(atan2(1.0, 1.0/0.0)))
  eval 1.0->atan2(1.0/0.0)->string()->assert_equal('0.0')
  call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0)))
  call assert_equal('nan', string(atan2(0.0/0.0, 1.0)))
  call assert_fails('call atan2("", -1)', 'E808:')
  call assert_fails('call atan2(-1, "")', 'E808:')
endfunc

func Test_tanh()
  call assert_equal('0.0', string(tanh(0.0)))
  call assert_equal('0.462117', string(tanh(0.5)))
  call assert_equal('-0.761594', string(tanh(-1.0)))
  eval -1.0->tanh()->string()->assert_equal('-0.761594')
  call assert_equal('1.0', string(tanh(1.0/0.0)))
  call assert_equal('-1.0', string(tanh(-1.0/0.0)))
  call assert_equal('nan', string(tanh(0.0/0.0)))
  call assert_fails('call tanh("")', 'E808:')
endfunc

func Test_fmod()
  call assert_equal('0.13', string(fmod(12.33, 1.22)))
  call assert_equal('-0.13', string(fmod(-12.33, 1.22)))
  call assert_equal('nan', string(fmod(1.0/0.0, 1.0)))
  eval (1.0/0.0)->fmod(1.0)->string()->assert_equal('nan')
  " On Windows we get "nan" instead of 1.0, accept both.
  let res = string(fmod(1.0, 1.0/0.0))
  if res != 'nan'
    call assert_equal('1.0', res)
  endif
  call assert_equal('nan', string(fmod(1.0, 0.0)))
  call assert_fails("call fmod('', 1.22)", 'E808:')
  call assert_fails("call fmod(12.33, '')", 'E808:')
endfunc

func Test_pow()
  call assert_equal('1.0', string(pow(0.0, 0.0)))
  call assert_equal('8.0', string(pow(2.0, 3.0)))
  eval 2.0->pow(3.0)->string()->assert_equal('8.0')
  call assert_equal('nan', string(pow(2.0, 0.0/0.0)))
  call assert_equal('nan', string(pow(0.0/0.0, 3.0)))
  call assert_equal('nan', string(pow(0.0/0.0, 3.0)))
  call assert_equal('inf', string(pow(2.0, 1.0/0.0)))
  call assert_equal('inf', string(pow(1.0/0.0, 3.0)))
  call assert_fails("call pow('', 2.0)", 'E808:')
  call assert_fails("call pow(2.0, '')", 'E808:')
endfunc

func Test_str2float()
  call assert_equal('1.0', string(str2float('1')))
  call assert_equal('1.0', string(str2float(' 1 ')))
  call assert_equal('1.0', string(str2float(' 1.0 ')))
  call assert_equal('1.23', string(str2float('1.23')))
  call assert_equal('1.23', string(str2float('1.23abc')))
  eval '1.23abc'->str2float()->string()->assert_equal('1.23')
  call assert_equal('1.0e40', string(str2float('1e40')))
  call assert_equal('-1.23', string(str2float('-1.23')))
  call assert_equal('1.23', string(str2float(' + 1.23 ')))

  call assert_equal('1.0', string(str2float('+1')))
  call assert_equal('1.0', string(str2float('+1')))
  call assert_equal('1.0', string(str2float(' +1 ')))
  call assert_equal('1.0', string(str2float(' + 1 ')))

  call assert_equal('-1.0', string(str2float('-1')))
  call assert_equal('-1.0', string(str2float('-1')))
  call assert_equal('-1.0', string(str2float(' -1 ')))
  call assert_equal('-1.0', string(str2float(' - 1 ')))

  call assert_equal('0.0', string(str2float('+0.0')))
  call assert_equal('-0.0', string(str2float('-0.0')))
  call assert_equal('inf', string(str2float('1e1000')))
  call assert_equal('inf', string(str2float('inf')))
  call assert_equal('-inf', string(str2float('-inf')))
  call assert_equal('inf', string(str2float('+inf')))
  call assert_equal('inf', string(str2float('Inf')))
  call assert_equal('inf', string(str2float('  +inf  ')))
  call assert_equal('nan', string(str2float('nan')))
  call assert_equal('nan', string(str2float('NaN')))
  call assert_equal('nan', string(str2float('  nan  ')))

  call assert_equal('123456.789', string(str2float("123'456.789", 1)))
  call assert_equal('123456.789', string(str2float("12'34'56.789", 1)))
  call assert_equal('123456.789', string(str2float("1'2'3'4'5'6.789", 1)))
  call assert_equal('1.0', string(str2float("1''2.3", 1)))
  call assert_equal('123456.7', string(str2float("123'456.7'89", 1)))

  call assert_equal(1.2, str2float(1.2, 0))
  call v9.CheckDefAndScriptFailure(['str2float(1.2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1'])
  call assert_fails("call str2float([])", 'E730:')
  call assert_fails("call str2float({})", 'E731:')
  call assert_fails("call str2float(function('string'))", 'E729:')
endfunc

def Test_float_quotes()
  call assert_equal('123456.789', string(123'456.789))
  call assert_equal('123456.789', string(12'34'56.789))
  call assert_equal('123456.789', string(1'2'3'4'5'6.789))

  call assert_fails("echo string(1''2.3)", 'E116:')
  call assert_fails("echo string(123'456.7'89)", 'E116:')
enddef

func Test_float_quotes_from_legacy()
  call assert_equal("\n123456.789", execute("vim9 echo 12'34'56.789"))
endfunc

func Test_float2nr()
  call assert_equal(1, float2nr(1.234))
  call assert_equal(123, float2nr(1.234e2))
  call assert_equal(12, float2nr(123.4e-1))
  eval 123.4e-1->float2nr()->assert_equal(12)
  let max_number = 1/0
  let min_number = -max_number
  call assert_equal(max_number/2+1, float2nr(pow(2, 62)))
  call assert_equal(max_number, float2nr(pow(2, 63)))
  call assert_equal(max_number, float2nr(pow(2, 64)))
  call assert_equal(min_number/2-1, float2nr(-pow(2, 62)))
  call assert_equal(min_number, float2nr(-pow(2, 63)))
  call assert_equal(min_number, float2nr(-pow(2, 64)))
endfunc

func Test_floor()
  call assert_equal('2.0', string(floor(2.0)))
  call assert_equal('2.0', string(floor(2.11)))
  call assert_equal('2.0', string(floor(2.99)))
  eval 2.99->floor()->string()->assert_equal('2.0')
  call assert_equal('-3.0', string(floor(-2.11)))
  call assert_equal('-3.0', string(floor(-2.99)))
  call assert_equal('nan', string(floor(0.0/0.0)))
  call assert_equal('inf', string(floor(1.0/0.0)))
  call assert_equal('-inf', string(floor(-1.0/0.0)))
  call assert_fails("call floor('')", 'E808:')
endfunc

func Test_ceil()
  call assert_equal('2.0', string(ceil(2.0)))
  call assert_equal('3.0', string(ceil(2.11)))
  call assert_equal('3.0', string(ceil(2.99)))
  call assert_equal('-2.0', string(ceil(-2.11)))
  eval -2.11->ceil()->string()->assert_equal('-2.0')
  call assert_equal('-2.0', string(ceil(-2.99)))
  call assert_equal('nan', string(ceil(0.0/0.0)))
  call assert_equal('inf', string(ceil(1.0/0.0)))
  call assert_equal('-inf', string(ceil(-1.0/0.0)))
  call assert_fails("call ceil('')", 'E808:')
endfunc

func Test_round()
  call assert_equal('2.0', string(round(2.1)))
  call assert_equal('3.0', string(round(2.5)))
  call assert_equal('3.0', string(round(2.9)))
  eval 2.9->round()->string()->assert_equal('3.0')
  call assert_equal('-2.0', string(round(-2.1)))
  call assert_equal('-3.0', string(round(-2.5)))
  call assert_equal('-3.0', string(round(-2.9)))
  call assert_equal('nan', string(round(0.0/0.0)))
  call assert_equal('inf', string(round(1.0/0.0)))
  call assert_equal('-inf', string(round(-1.0/0.0)))
  call assert_fails("call round('')", 'E808:')
endfunc

func Test_trunc()
  call assert_equal('2.0', string(trunc(2.1)))
  call assert_equal('2.0', string(trunc(2.5)))
  call assert_equal('2.0', string(trunc(2.9)))
  eval 2.9->trunc()->string()->assert_equal('2.0')
  call assert_equal('-2.0', string(trunc(-2.1)))
  call assert_equal('-2.0', string(trunc(-2.5)))
  call assert_equal('-2.0', string(trunc(-2.9)))
  call assert_equal('nan', string(trunc(0.0/0.0)))
  call assert_equal('inf', string(trunc(1.0/0.0)))
  call assert_equal('-inf', string(trunc(-1.0/0.0)))
  call assert_fails("call trunc('')", 'E808:')
endfunc

func Test_isinf()
  call assert_equal(1, isinf(1.0/0.0))
  call assert_equal(-1, isinf(-1.0/0.0))
  eval (-1.0/0.0)->isinf()->assert_equal(-1)
  call assert_false(isinf(1.0))
  call assert_false(isinf(0.0/0.0))
  call assert_false(isinf('a'))
  call assert_false(isinf([]))
  call assert_false(isinf({}))
endfunc

func Test_isnan()
  call assert_true(isnan(0.0/0.0))
  call assert_false(isnan(1.0))
  call assert_false(isnan(1.0/0.0))
  eval (1.0/0.0)->isnan()->assert_false()
  call assert_false(isnan(-1.0/0.0))
  call assert_false(isnan('a'))
  call assert_false(isnan([]))
  call assert_false(isnan({}))
endfunc

" This was converted from test65
func Test_float_misc()
  call assert_equal('123.456000', printf('%f', 123.456))
  call assert_equal('1.234560e+02', printf('%e', 123.456))
  call assert_equal('123.456', printf('%g', 123.456))
  " +=
  let v = 1.234
  let v += 6.543
  call assert_equal('7.777', printf('%g', v))
  let v = 1.234
  let v += 5
  call assert_equal('6.234', printf('%g', v))
  let v = 5
  let v += 3.333
  call assert_equal('8.333', string(v))
  " ==
  let v = 1.234
  call assert_true(v == 1.234)
  call assert_false(v == 1.2341)
  " add-subtract
  call assert_equal('5.234', printf('%g', 4 + 1.234))
  call assert_equal('-6.766', printf('%g', 1.234 - 8))
  " mult-div
  call assert_equal('4.936', printf('%g', 4 * 1.234))
  call assert_equal('0.003241', printf('%g', 4.0 / 1234))
  " dict
  call assert_equal("{'x': 1.234, 'y': -2.0e20}", string({'x': 1.234, 'y': -2.0e20}))
  " list
  call assert_equal('[-123.4, 2.0e-20]', string([-123.4, 2.0e-20]))
endfunc

" vim: shiftwidth=2 sts=2 expandtab