Skip to content

Big Integer Support #876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 205 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
205 commits
Select commit Hold shift + click to select a range
ce7cba8
Working bigints with no tests and some unfixed corner cases
hikari-no-yume Jun 6, 2014
fe5be2d
Less quirky left shift behaviour
hikari-no-yume Jun 11, 2014
42af703
Fixed zend_bigint_modulus so it would use sign of dividend
hikari-no-yume Jun 11, 2014
1592f6d
Made increment and decrement overflow to bigint
hikari-no-yume Jun 11, 2014
e75e4aa
Updated arithmetic 64-bit operator tests
hikari-no-yume Jun 11, 2014
16aee40
Fixed memory leak when converting to string
hikari-no-yume Jun 12, 2014
ed8c9e5
Updated << and >> tests
hikari-no-yume Jun 12, 2014
c193ed4
Updated binary literals test
hikari-no-yume Jun 12, 2014
32a09b4
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jun 13, 2014
9a86549
Noted you can use bigint result as operand
hikari-no-yume Jun 14, 2014
d571c34
_init_strtol and _release; is_numeric_string support
hikari-no-yume Jun 17, 2014
e388c26
Updated integer casting to work for bigints
hikari-no-yume Jun 18, 2014
3357747
Updated decrement test
hikari-no-yume Jun 18, 2014
16e0c79
Updated overflow test
hikari-no-yume Jun 18, 2014
6f3d4b7
Fixed cast check
hikari-no-yume Jun 18, 2014
b2fd363
Added zend_bigint_alloc to avoid writing emalloc(sizeof(zend_bigint))
hikari-no-yume Jun 18, 2014
913bbf1
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jun 18, 2014
2e6170a
Fixed more is_numeric_string refs (well, they compile at least)
hikari-no-yume Jun 18, 2014
017401b
Fixed casting of objects to integers
hikari-no-yume Jun 18, 2014
d292445
Updated max 64-bit >=, ==, != and <= tests
hikari-no-yume Jun 19, 2014
8d5cf28
Updated double to string conversion test
hikari-no-yume Jun 19, 2014
9a68d02
Updated overflow and underflow tests
hikari-no-yume Jun 19, 2014
7ffe193
Updated lval to dval test
hikari-no-yume Jun 20, 2014
d1bb53d
Restored erroneously removed precision ini directives
hikari-no-yume Jun 20, 2014
2815530
Updated 64-bit signed multiply test
hikari-no-yume Jun 20, 2014
3aaab60
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jun 20, 2014
2ebc4b5
Fixed settype and StdObject handler cast
hikari-no-yume Jun 20, 2014
89d01c4
Added bigint support to debug_zval_dump
hikari-no-yume Jun 20, 2014
f07c4f7
When converting to IS_BIGINT_OR_LONG, convert doubles to long if poss…
hikari-no-yume Jun 21, 2014
c088c89
Fixed is_numeric_string bigint memory leak
hikari-no-yume Jun 21, 2014
e926e6f
Fixed zend_bigint_init_strtol and made zendi_smart_strcmp work w/ big…
hikari-no-yume Jun 21, 2014
8e655f9
Fixed is_numeric_string double handling
hikari-no-yume Jun 21, 2014
c39d51b
Updated string offset error test and fixed bigint offset handling
hikari-no-yume Jun 21, 2014
4c62980
Updated max and min tests
hikari-no-yume Jun 21, 2014
11c5f3f
Fixed weird )}/)} mixup (how did that even compile?!)
hikari-no-yume Jun 21, 2014
680ccc0
ARM not ASM
hikari-no-yume Jun 21, 2014
360e1b0
Work around gmp overflow error by checking limits ourselves and erroring
hikari-no-yume Jun 23, 2014
a2eb729
Added UNEXPECTED() around assert_limbs conditionals
hikari-no-yume Jun 23, 2014
cde98fb
Multiple stones with single bird: Macro for op1/op2 free, array_produ…
hikari-no-yume Jun 23, 2014
819d740
Updated array_sum test
hikari-no-yume Jun 23, 2014
b66c149
Updated array_product test
hikari-no-yume Jun 24, 2014
afdeb32
Made abs() work with bigints and implemented RETURN_BIGINT in the pro…
hikari-no-yume Jun 24, 2014
a31aee1
Made floor, ceil and round work with bigints
hikari-no-yume Jun 24, 2014
8b40057
Fixed inconsistent indentation type
hikari-no-yume Jun 24, 2014
792716f
Made zend_language_scanner finally use zend_bigint_init_from_string_l…
hikari-no-yume Jun 24, 2014
66fb2fe
Ditto for hex
hikari-no-yume Jun 24, 2014
7dbfeaf
Use zend_bigint_release here
hikari-no-yume Jun 24, 2014
2933c87
Restored %d and %s mistakenly removed from EXPECTFs
hikari-no-yume Jun 24, 2014
67d6574
Fixed limb size overflow (defeating overflow check)
hikari-no-yume Jun 24, 2014
b3b24f3
Made is_int work correctly with bigints and updated tests
hikari-no-yume Jun 24, 2014
1d36805
Added tests for bigints
hikari-no-yume Jun 24, 2014
10f485c
Added tests for new bitwise shift behaviour
hikari-no-yume Jun 24, 2014
74abff1
Updated tests for trigonometric, logarithmic and power math functions
hikari-no-yume Jun 24, 2014
d3d2891
Updated bindec and decbin/hex/oct tests
hikari-no-yume Jun 24, 2014
f3fa086
Updated is_finite/infinite/nan tests
hikari-no-yume Jun 24, 2014
6596d89
Updated chunk_split tests
hikari-no-yume Jun 24, 2014
38a38ba
Fixed ZEND_SIGNED_MULTIPLY on 32-bit
hikari-no-yume Jun 25, 2014
fc7d6a1
Fixed behaviour of / -1 for LONG_MIN
hikari-no-yume Jun 25, 2014
fa16a82
Fixed behaviour of right shift on a bigint
hikari-no-yume Jun 25, 2014
ed30e84
Fixed memory leak when comparing strings that juggle to bigints
hikari-no-yume Jun 25, 2014
a5f94a0
Updated << 32-bit test
hikari-no-yume Jun 25, 2014
7f997cd
Updated 32-bit comparison operator tests
hikari-no-yume Jun 25, 2014
5706f02
Updated 32-bit binary literals test
hikari-no-yume Jun 25, 2014
7b9f37b
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jun 25, 2014
02e91a1
More efficient handling of bigints as array indices
hikari-no-yume Jun 25, 2014
650e922
Updated bug #54547 test
hikari-no-yume Jun 25, 2014
9a61860
Updated decrement test (properly, this time)
hikari-no-yume Jun 25, 2014
edf7625
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jun 28, 2014
a976a6e
Updated more tests
hikari-no-yume Jun 29, 2014
f181e4c
Commented things out properly
hikari-no-yume Jun 29, 2014
b5ae715
Fixed ++ test properly
hikari-no-yume Jun 29, 2014
56a34d2
Made test 64-bit only which was mistakenly universal
hikari-no-yume Jul 1, 2014
96e6af0
Updated array_product 32-bit test
hikari-no-yume Jul 1, 2014
9f1bda1
Merge branch 'phpng-bigint' of ssh://localhost:22000/home/ajf/Project…
hikari-no-yume Jul 1, 2014
56681b3
Prevent crash when converting float INF value to int
hikari-no-yume Jul 3, 2014
266ca34
Fixed test in preceding commit
hikari-no-yume Jul 3, 2014
4ed6b15
Fixed common case INFINITY definition
hikari-no-yume Jul 3, 2014
146d0e9
Corrected definition of zend_dval_to_big_or_lval for lval case
hikari-no-yume Jul 3, 2014
e786381
Cast NaN to zero
hikari-no-yume Jul 3, 2014
52edb8c
Nicer formatting for INFINITY definition
hikari-no-yume Jul 3, 2014
98e70c7
Fixed 32-bit double to string conversion test
hikari-no-yume Jul 3, 2014
b5cd462
E_RECOVERABLE_ERROR if too large int passed for long func param
hikari-no-yume Jul 7, 2014
3ab6df6
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Jul 20, 2014
8e2c91b
Fixed missing TSRMLS_CC
hikari-no-yume Jul 20, 2014
74c5faf
Updated is_numeric_str_function
hikari-no-yume Jul 20, 2014
434c260
Add those proper /* {{{ */ annotation thingies
hikari-no-yume Jul 21, 2014
291e638
Perhaps "saturates" is clearer?
hikari-no-yume Jul 24, 2014
2c1a4cc
Merge branch 'phpng' into phpng-bigint
hikari-no-yume Aug 5, 2014
2cf76ab
Compiler warnings fixes
hikari-no-yume Aug 5, 2014
b8c8be6
Merge branch 'master' into phpng-bigint
hikari-no-yume Aug 15, 2014
d0a6cfa
Merge branch 'master' into phpng-bigint
hikari-no-yume Aug 27, 2014
cafb5c9
Made zend_bigint functions take zend_long/zend_ulongs
hikari-no-yume Aug 27, 2014
de41750
Fixed constants in Zend/zend_multiply.h
hikari-no-yume Aug 27, 2014
0c0fc5d
Fixed neg shift test
hikari-no-yume Aug 27, 2014
12b337c
Little fixes
hikari-no-yume Aug 27, 2014
3526422
Got rid of fast decrement and increment functions to remove segfaults
hikari-no-yume Aug 27, 2014
7685bdb
Handle bigints for var_export
hikari-no-yume Aug 28, 2014
e91ed13
Fixed is_long, special-cased aliases, warned of special cases, fixed …
hikari-no-yume Aug 28, 2014
90576d9
oops
hikari-no-yume Aug 28, 2014
3a0e870
Clarity
hikari-no-yume Aug 28, 2014
7a7605b
Merge branch 'master' into phpng-bigint
hikari-no-yume Aug 28, 2014
8758d4f
Removed 32-bit skip condition
hikari-no-yume Aug 28, 2014
23f53e2
Merge branch 'master' into phpng-bigint
hikari-no-yume Sep 21, 2014
c9b7ae6
Unfinished business
hikari-no-yume Sep 21, 2014
824a2f1
Saturation and overflow modes, no more errors on bigint passed for long
hikari-no-yume Sep 21, 2014
cede499
Higher accuracy when doing a floating-point division of two bigints
hikari-no-yume Sep 21, 2014
91d830b
Merge branch 'master' into phpng-bigint
hikari-no-yume Sep 30, 2014
1f667d5
Removed bigint-specific INFINITY workaround in favour of Zend define
hikari-no-yume Sep 30, 2014
4848dd3
Merge branch 'master' into phpng-bigint
hikari-no-yume Oct 14, 2014
93aba7a
Removed now-invalid test
hikari-no-yume Oct 17, 2014
a096296
Fixed bigint passing for double paramters
hikari-no-yume Oct 17, 2014
d3909c5
Remove definition of zend_bigint from zend_types.h to ensure abstraction
hikari-no-yume Oct 17, 2014
075fcb4
Fixed zend_get_bigint_or_long to return zend_long
hikari-no-yume Oct 17, 2014
be58258
Switchable bigint backends, beginning of LibTomMath backend as default
hikari-no-yume Oct 18, 2014
f4d162c
Fixed bigint_to_bool, implemented _bigint_to_double
hikari-no-yume Oct 19, 2014
67ed2b8
Stray i
hikari-no-yume Oct 19, 2014
70e3692
Fixed strict equality for bigint/long
hikari-no-yume Oct 22, 2014
34cc2d9
Merge branch 'bigint' into bigint-libtommath
hikari-no-yume Oct 22, 2014
6820518
Fixed strict equality for bigint/long
hikari-no-yume Oct 22, 2014
9b0cab3
Report Big Integer Support backend in phpinfo!
hikari-no-yume Nov 24, 2014
b997029
Merge branch 'master' into bigint-libtommath
hikari-no-yume Nov 29, 2014
747340e
Implement basics of LibTomMath long<->bigint conversion, addition, su…
hikari-no-yume Dec 1, 2014
90db70a
Implement division, multiplication, exponentiation for LibTomMath
hikari-no-yume Dec 2, 2014
6433e27
Implement copy-on-write for bigints
hikari-no-yume Dec 4, 2014
7a65a9b
Merge branch 'master' into bigint-libtommath
hikari-no-yume Dec 4, 2014
a1a4b06
Merge branch 'master' into bigint-libtommath
hikari-no-yume Dec 6, 2014
7da5ba2
Build LibTomMath as part of Zend (bundles single-file version of LibT…
hikari-no-yume Dec 7, 2014
996db9c
Removed redundant long_(or|and|xor) functions
hikari-no-yume Dec 7, 2014
aab879b
Move documentation comments to header, since we have two implementations
hikari-no-yume Dec 7, 2014
8ff1e7b
Relocate dragons
hikari-no-yume Dec 7, 2014
3a70756
Group similar functions in header, only document the group
hikari-no-yume Dec 7, 2014
8939011
Error-checking, more ops implemented
hikari-no-yume Dec 8, 2014
8441f8b
Fixed 32-bit signed multiply
hikari-no-yume Dec 8, 2014
872025a
Add missing LibTomMath files; Add Zend/libtommath to includes
hikari-no-yume Dec 8, 2014
785c9b7
Remove build-breaking `static` qualifiers
hikari-no-yume Dec 8, 2014
974d23f
Only overwrite result for bigint ops if result can be assumed initial…
hikari-no-yume Dec 8, 2014
f8fea77
Fix zend_bigint_to_zend_string using uninitialised memory for string …
hikari-no-yume Dec 8, 2014
f715285
fixed zend_bigint_subtract_long
hikari-no-yume Dec 8, 2014
2a7c168
Fix modulus sign behaviour
hikari-no-yume Dec 8, 2014
c3e0bbb
Fixed exponent size check for bitwise shifts
hikari-no-yume Dec 8, 2014
ada2fff
Merge branch 'master' into bigint-libtommath
hikari-no-yume Dec 23, 2014
4f541ac
Fix right shift for negative op1 in LibTomMath
hikari-no-yume Dec 23, 2014
7f5960b
Merge branch 'master' into bigint-libtommath
hikari-no-yume Dec 23, 2014
b1431fc
Merge branch 'master' into bigint-libtommath
hikari-no-yume Dec 29, 2014
8e5b622
Implemented zend_bigint_to_long for LibTomMath
hikari-no-yume Dec 29, 2014
000a6bc
Remove support for hex number from is_numeric_string
nikic Apr 17, 2012
60e3ec2
Merge branch 'master' into bigint-libtommath
hikari-no-yume Jan 5, 2015
bf50e8d
Fix compiler warnings in LibTomMath bigint implementation
hikari-no-yume Jan 5, 2015
dd1c4cd
Add zpp i/I (Z_PARAM_BIGINT_OR_LONG/_BIGINT), update intdiv() to use it
hikari-no-yume Jan 5, 2015
bd62084
Note LibTomMath in README.REDIST.BINS
hikari-no-yume Jan 5, 2015
5dc8960
Removed accidentally committed file
hikari-no-yume Jan 6, 2015
bdcd9bb
Remove commented-out inline asm, use clang/gcc intrinsics
hikari-no-yume Jan 6, 2015
737e8d5
Merge branch 'master' into bigint-libtommath
hikari-no-yume Jan 6, 2015
e5e12a3
Do conditional compilation the "right" way
hikari-no-yume Jan 7, 2015
f57ff7b
Merge branch 'bigint' into bigint-libtommath
hikari-no-yume Jan 7, 2015
813aaf0
Merge branch 'master' into bigint
hikari-no-yume Jan 7, 2015
fb56f86
Merge branch 'master' into bigint
hikari-no-yume Jan 7, 2015
bdba659
Merge branch 'master' into bigint
hikari-no-yume Jan 12, 2015
31b41cf
Fix intdiv test on 32-bit
hikari-no-yume Jan 12, 2015
0c9b04a
Merge branch 'master' into bigint
hikari-no-yume Jan 15, 2015
deb077e
Merge branch 'master' into bigint
hikari-no-yume Jan 15, 2015
9ac691f
unserialize() and serialize() support
hikari-no-yume Jan 15, 2015
fb3fe8b
fix datatype
weltling Jan 15, 2015
eaf799b
C89 compat
weltling Jan 15, 2015
b184efa
%s,__out,__bires,g ... to avoid symbol clashing
weltling Jan 15, 2015
95ae153
enable MPIR by default
weltling Jan 15, 2015
d1d3aba
Remove code made redundant by ZPP Failure on Overflow patch
hikari-no-yume Jan 15, 2015
b00590b
Merge branch 'master' into bigint
hikari-no-yume Jan 15, 2015
9cc287b
Remove zend_bigint_alloc, make zend_bigint_init functions alloc
hikari-no-yume Jan 16, 2015
d2ece0e
Remove leftover stuff in zend_bigint.h
hikari-no-yume Jan 16, 2015
16074f0
Bitwise op clarity
hikari-no-yume Jan 16, 2015
2e90285
Note modulus has sign of divisor
hikari-no-yume Jan 16, 2015
481bc1e
Implement two's complement behaviour for bitwise ops
hikari-no-yume Jan 16, 2015
d88ceba
Merge branch 'master' into bigint
hikari-no-yume Jan 16, 2015
16d5f96
fix is_numerc_string call
weltling Jan 16, 2015
537c4f1
add bigint support to smart_str
weltling Jan 16, 2015
ed74080
basic fixes to ext/json
weltling Jan 16, 2015
4483117
fix is_numeric_string usage in ext/filter
weltling Jan 16, 2015
fcb824e
basic fix to ext/intl
weltling Jan 16, 2015
dd30498
Missing flag in config.w32
hikari-no-yume Jan 16, 2015
f584135
Fully port ext/json :)
hikari-no-yume Jan 16, 2015
01d5603
basic fixes to pdo+bigint
weltling Jan 17, 2015
5b68c0e
Merge remote-tracking branch 'php/master' into bigint2
weltling Jan 17, 2015
6932b86
fix decbin, decoct, dechex ... tests to go
weltling Jan 17, 2015
8b11093
basic bigint fixes to ext/sockets
weltling Jan 17, 2015
7d17894
basic bigint fixes to ext/soap
weltling Jan 17, 2015
fc95e8f
fix some datatypes
weltling Jan 17, 2015
d429779
fix uninitialize local var
weltling Jan 17, 2015
e1115ed
these functions have to return a value
weltling Jan 17, 2015
caa4c6d
use better API
weltling Jan 17, 2015
1a3f0fc
apply suggested fixes
weltling Jan 17, 2015
f3408aa
Merge branch 'master' into bigint (+ adds octal in zend_bigint_init_s…
hikari-no-yume Jan 17, 2015
c332ae8
convert_to_bigint_or_long will auto-demote
hikari-no-yume Jan 17, 2015
93a4e06
Merge remote-tracking branch 'ajf/bigint' into bigint2
weltling Jan 18, 2015
d065d81
Merge remote-tracking branch 'php/master' into bigint2
weltling Jan 18, 2015
a791e95
Merge branch 'master' into bigint
hikari-no-yume Jan 18, 2015
f62496a
Merge remote-tracking branch 'weltling/bigint2' into bigint
hikari-no-yume Jan 18, 2015
4078545
fix decbin/oct/hex memleak, add zend_bigint_to_zend_string_base
hikari-no-yume Jan 18, 2015
cfaf8df
Merge branch 'master' into bigint
hikari-no-yume Jan 21, 2015
a821230
Use __builtin_clz for shift-left overflow check
hikari-no-yume Jan 21, 2015
78715e3
Avoid undefined behaviour
hikari-no-yume Jan 21, 2015
0c2f757
Be proper!
hikari-no-yume Jan 21, 2015
b91a808
Merge branch 'master' into bigint
hikari-no-yume Jan 28, 2015
fab5efb
Revert "fix decbin, decoct, dechex ... tests to go"
hikari-no-yume Jan 28, 2015
c82e66d
Merge remote-tracking branch 'nikic/noHexInIsNumericString' into bigint
hikari-no-yume Feb 10, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
When converting to IS_BIGINT_OR_LONG, convert doubles to long if poss…
…ible
  • Loading branch information
hikari-no-yume committed Jun 21, 2014
commit f07c4f7fe4dbdfd93ede06611ae2e2ccda904305
21 changes: 12 additions & 9 deletions Zend/zend_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
/* {{{ zendi_convert_to_bigint_or_long */
#define zendi_convert_to_bigint_or_long(op, holder, result) \
if (op == result) { \
convert_to_bigint(op); \
convert_to_bigint_or_long(op); \
} else if (!(Z_TYPE_P(op) == IS_LONG || Z_TYPE_P(op) == IS_BIGINT)) {\
switch (Z_TYPE_P(op)) { \
case IS_NULL: \
Expand All @@ -378,8 +378,11 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
ZVAL_LONG(&holder, 1); \
break; \
case IS_DOUBLE: \
ZVAL_NEW_BIGINT(&holder); \
zend_bigint_init_from_double(Z_BIG(holder), Z_DVAL_P(op));\
if (zend_dval_to_big_or_lval(Z_DVAL_P(op), &Z_LVAL(holder), &Z_BIG(holder)) == IS_BIGINT) {\
ZVAL_BIGINT(&holder, Z_BIG(holder)); \
} else { \
ZVAL_LONG(&holder, Z_LVAL(holder)); \
} \
break; \
case IS_STRING: \
errno = 0; \
Expand Down Expand Up @@ -665,9 +668,11 @@ ZEND_API void convert_to_bigint_or_long_base(zval *op, int base) /* {{{ */
break;
case IS_DOUBLE:
{
double d = Z_DVAL_P(op);
ZVAL_NEW_BIGINT(op);
zend_bigint_init_from_double(Z_BIG_P(op), d);
if (zend_dval_to_big_or_lval(Z_DVAL_P(op), &Z_LVAL_P(op), &Z_BIG_P(op)) == IS_BIGINT) {
ZVAL_BIGINT(op, Z_BIG_P(op));
} else {
ZVAL_LONG(op, Z_LVAL_P(op));
}
}
break;
case IS_BIGINT:
Expand Down Expand Up @@ -1179,9 +1184,7 @@ ZEND_API zend_uchar _zval_get_bigint_or_long_func(zval *op, long *lval, zend_big
*lval = Z_LVAL_P(op);
return IS_LONG;
case IS_DOUBLE:
*big = zend_bigint_alloc();
zend_bigint_init_from_double(*big, Z_DVAL_P(op));
return IS_BIGINT;
return zend_dval_to_big_or_lval(Z_DVAL_P(op), lval, big);
case IS_BIGINT:
*big = Z_BIG_P(op);
return IS_BIGINT;
Expand Down
18 changes: 18 additions & 0 deletions Zend/zend_operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ static zend_always_inline long zend_dval_to_lval(double d)
#endif
/* }}} */

static zend_always_inline zend_uchar zend_dval_to_big_or_lval(double d, long *lval, zend_bigint **big)
{
#if SIZEOF_LONG == 4
if (d > LONG_MAX || d < LONG_MIN) {
#else
/* >= as (double)LONG_MAX is outside signed range */
if (d >= LONG_MAX || d < LONG_MIN) {
#endif
*big = zend_bigint_alloc();
zend_bigint_init_from_double(*big, d);
return IS_BIGINT;
} else {
*lval = (long)d;
return IS_LONG;
}
}
/* }}} */

#define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#define ZEND_IS_XDIGIT(c) (((c) >= 'A' && (c) <= 'F') || ((c) >= 'a' && (c) <= 'f'))

Expand Down