mirror of
https://github.com/ArashPartow/exprtk.git
synced 2025-06-12 16:27:23 +00:00
C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
209
exprtk_test.cpp
209
exprtk_test.cpp
@ -1409,27 +1409,173 @@ inline bool run_test02()
|
||||
test_ab<T>("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("a[2:6] == b" ,"0123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("a == b[2:6]" ,"23456","0123456789" ,T(1.0)),
|
||||
test_ab<T>("a[1+1:2*3] == b" ,"0123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("a == b[4/2:sqrt(36)]" ,"23456","0123456789" ,T(1.0)),
|
||||
test_ab<T>("a[0:6] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[:6] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[4/2-2:2+4] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[:12/2] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[0:] == b" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a[:] == b" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a == b[0:6]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[:6]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[4/2-2:2+4]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[:12/2]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[0:]" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a == b[:]" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a[:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[0:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[:] == b[10:]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == '0123456789' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == '0123456789'[:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == '0123456789'[0:]","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == '0123456789'[:9]","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[:9] == '0123456789'[:9]","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[10:] == '0123456789'[:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != '123456789' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != '123456789'[:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != '123456789'[0:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != '123456789'[:8] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[:9] != '123456789'[:8] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[10:] != '123456789'[:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[2*6:10+6] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'0123456789' == '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'0123456789'[:] == '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'0123456789'[0:] == '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'0123456789'[:9] == '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'0123456789'[:9] == '01234567890123456789'[:9] ","","",T(1.0)),
|
||||
test_ab<T>("'0123456789'[:] == '01234567890123456789'[10:]","","",T(1.0)),
|
||||
test_ab<T>("'123456789' != '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'123456789'[:] != '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'123456789'[0:] != '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'123456789'[:8] != '01234567890123456789'[0:9]","","",T(1.0)),
|
||||
test_ab<T>("'123456789'[:8] != '01234567890123456789'[:9] ","","",T(1.0)),
|
||||
test_ab<T>("'123456789'[:] != '01234567890123456789'[10:]","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[2*6:10+6] ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0: 6] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[2: r1] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0:3*2] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[1+1:r1] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0: ] == '234567890123456789' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[: r1] == '0123456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0:r1] == '23456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0:r1+2] == '2345678' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r0+2:r1] == '456' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[r1-r0:] == '4567890123456789' ","","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[:r1-r0] == '01234' ","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[r0: 6] ","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[2: r1] ","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[r0:3*2] ","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[1+1:r1] ","","",T(1.0)),
|
||||
test_ab<T>("'234567890123456789' == '01234567890123456789'[r0: ] ","","",T(1.0)),
|
||||
test_ab<T>("'0123456' == '01234567890123456789'[: r1] ","","",T(1.0)),
|
||||
test_ab<T>("'23456' == '01234567890123456789'[r0:r1] ","","",T(1.0)),
|
||||
test_ab<T>("'2345678' == '01234567890123456789'[r0:r1+2] ","","",T(1.0)),
|
||||
test_ab<T>("'456' == '01234567890123456789'[r0+2:r1] ","","",T(1.0)),
|
||||
test_ab<T>("'4567890123456789' == '01234567890123456789'[r1-r0:] ","","",T(1.0)),
|
||||
test_ab<T>("'01234' == '01234567890123456789'[:r1-r0] ","","",T(1.0)),
|
||||
test_ab<T>("a[r0: 6] == '23456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[2: r1] == '23456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0:3*2] == '23456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[1+1:r1] == '23456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0: ] == '234567890123456789' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[: r1] == '0123456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0:r1] == '23456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0:r1+2] == '2345678' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0+2:r1] == '456' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r1-r0:] == '4567890123456789' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[:r1-r0] == '01234' ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'23456' == a[r0: 6] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'23456' == a[2: r1] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'23456' == a[r0:3*2] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'23456' == a[1+1:r1] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'234567890123456789' == a[r0: ] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'0123456' == a[: r1] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'23456' == a[r0:r1] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'2345678' == a[r0:r1+2] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'456' == a[r0+2:r1] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'4567890123456789' == a[r1-r0:] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("'01234' == a[:r1-r0] ","01234567890123456789","",T(1.0)),
|
||||
test_ab<T>("a[r0: 6] == b " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("a[2: r1] == b " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("a[r0:3*2] == b " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("a[1+1:r1] == b " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("a[r0: ] == b " ,"01234567890123456789","234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[: r1] == b " ,"01234567890123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[r0:r1] == b " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("a[r0:r1+2] == b " ,"01234567890123456789","2345678",T(1.0)),
|
||||
test_ab<T>("a[r0+2:r1] == b " ,"01234567890123456789","456",T(1.0)),
|
||||
test_ab<T>("a[r1-r0:] == b " ,"01234567890123456789","4567890123456789",T(1.0)),
|
||||
test_ab<T>("a[:r1-r0] == b " ,"01234567890123456789","01234",T(1.0)),
|
||||
test_ab<T>("b == a[r0: 6] " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("b == a[2: r1] " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("b == a[r0:3*2] " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("b == a[1+1:r1] " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("b == a[r0: ] " ,"01234567890123456789","234567890123456789",T(1.0)),
|
||||
test_ab<T>("b == a[: r1] " ,"01234567890123456789","0123456",T(1.0)),
|
||||
test_ab<T>("b == a[r0:r1] " ,"01234567890123456789","23456",T(1.0)),
|
||||
test_ab<T>("b == a[r0:r1+2] " ,"01234567890123456789","2345678",T(1.0)),
|
||||
test_ab<T>("b == a[r0+2:r1] " ,"01234567890123456789","456",T(1.0)),
|
||||
test_ab<T>("b == a[r1-r0:] " ,"01234567890123456789","4567890123456789",T(1.0)),
|
||||
test_ab<T>("b == a[:r1-r0] " ,"01234567890123456789","01234",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == a ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == a[:] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == a[0:] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] == a[:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[:9] == a[:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[10:] == a[:] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != a ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != a[:] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != a[0:] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[0:9] != a[:8] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[:9] != a[:8] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[10:] != a[:] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("'01234567890123456789'[2*6:10+6] == a","23456" ,"",T(1.0)),
|
||||
test_ab<T>("'23456' == a[:] ","23456" ,"",T(1.0)),
|
||||
test_ab<T>("a == '01234567890123456789'[0:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a[:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a[0:] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a[:9] == '01234567890123456789'[0:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a[:9] == '01234567890123456789'[:9] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a[:] == '01234567890123456789'[10:] ","0123456789","",T(1.0)),
|
||||
test_ab<T>("a != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a[:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a[0:] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a[:8] != '01234567890123456789'[0:9] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a[:8] != '01234567890123456789'[:9] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a[:] != '01234567890123456789'[10:] ","123456789" ,"",T(1.0)),
|
||||
test_ab<T>("a == '01234567890123456789'[2*6:10+6]","23456" ,"",T(1.0)),
|
||||
test_ab<T>("a[:] == '23456' ","23456" ,"",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b[:] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b[0:] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[:9] == b[:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[10:] == b[:] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] != b ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[0:9] != b[:] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[0:9] != b[0:] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[0:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[:9] != b[:8] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[10:] != b[:] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("a[2*6:10+6] == b ","01234567890123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("b == a[0:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b[:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b[0:] == a[0:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b[:9] == a[0:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b[:9] == a[:9] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b[:] == a[10:] ","01234567890123456789","0123456789",T(1.0)),
|
||||
test_ab<T>("b != a[0:9] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b[:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b[0:] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b[:8] != a[0:9] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b[:8] != a[:9] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b[:] != a[10:] ","01234567890123456789","123456789" ,T(1.0)),
|
||||
test_ab<T>("b == a[2*6:10+6] ","01234567890123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("a[2:6] == b" ,"0123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("a == b[2:6]" ,"23456","0123456789" ,T(1.0)),
|
||||
test_ab<T>("a[1+1:2*3] == b" ,"0123456789","23456" ,T(1.0)),
|
||||
test_ab<T>("a == b[4/2:sqrt(36)]","23456","0123456789" ,T(1.0)),
|
||||
test_ab<T>("a[0:6] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[:6] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[4/2-2:2+4] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[:12/2] == b" ,"0123456789","0123456",T(1.0)),
|
||||
test_ab<T>("a[0:] == b" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a[:] == b" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a == b[0:6]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[:6]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[4/2-2:2+4]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[:12/2]" ,"0123456","0123456789",T(1.0)),
|
||||
test_ab<T>("a == b[0:]" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a == b[:]" ,"0123456","0123456" ,T(1.0)),
|
||||
test_ab<T>("a[:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[0:9] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[0:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[:] == b[0:9]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("a[:] == b[10:]" ,"0123456789","01234567890123456789",T(1.0)),
|
||||
test_ab<T>("'!@#$%^&*([{}])-=' != ')]}{[(*&^%$#@!'","","",T(1.0)),
|
||||
test_ab<T>("('!@#$%^&*([{}])-=') != (')]}{[(*&^%$#@!')","","",T(1.0)),
|
||||
test_ab<T>("{[('a')]} == [{('a')}]","","",T(1.0)),
|
||||
@ -1452,10 +1598,15 @@ inline bool run_test02()
|
||||
std::string str_b;
|
||||
std::string str_c;
|
||||
|
||||
T r0 = T(2);
|
||||
T r1 = T(6);
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
symbol_table.add_stringvar("a",str_a);
|
||||
symbol_table.add_stringvar("b",str_b);
|
||||
symbol_table.add_stringvar("c",str_c);
|
||||
symbol_table.add_stringvar("a" ,str_a);
|
||||
symbol_table.add_stringvar("b" ,str_b);
|
||||
symbol_table.add_stringvar("c" ,str_c);
|
||||
symbol_table.add_variable ("r0", r0);
|
||||
symbol_table.add_variable ("r1", r1);
|
||||
|
||||
exprtk::expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
@ -2976,11 +3127,11 @@ inline bool run_test15()
|
||||
"/* Comment 11*/2 - (x + y) / z/* Comment 12*/",
|
||||
"/* Comment 13*/2 - (x + y) / z/* Comment 14*/\n",
|
||||
"2 - /* Comment 15 */(x + y) / z",
|
||||
"2 - /* Comment 15 */(x + y) /* Comment 16 *// z \n",
|
||||
"2 - /* Comment 17 */(x + y) /* Comment 18 */ / z //Comment 19\n",
|
||||
"2 - /* Comment 20 */(x + y) /* Comment 21 */ / z #Comment 22\n",
|
||||
"2 - /* Comment 23 */(x + y) /* Comment 24 */ / z //Comment 25",
|
||||
"2 - /* Comment 26 */(x + y) /* Comment 27 */ / z #Comment 28"
|
||||
"2 - /* Comment 16 */(x + y) /* Comment 17 *// z \n",
|
||||
"2 - /* Comment 18 */(x + y) /* Comment 19 */ / z //Comment 20\n",
|
||||
"2 - /* Comment 21 */(x + y) /* Comment 22 */ / z #Comment 23\n",
|
||||
"2 - /* Comment 24 */(x + y) /* Comment 25 */ / z //Comment 26",
|
||||
"2 - /* Comment 27 */(x + y) /* Comment 28 */ / z #Comment 29"
|
||||
};
|
||||
static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string);
|
||||
|
||||
|
Reference in New Issue
Block a user