@@ -327,6 +327,10 @@ mod tests {
327327 set pi_fancy π
328328 set e @e
329329 noop
330+ set a 1e308
331+ set b 1e309
332+ set c -1e308
333+ set d -1e309
330334 "# ,
331335 ) ;
332336
@@ -373,6 +377,16 @@ mod tests {
373377 LValue :: Number ( variables:: E . into( ) )
374378 ) ;
375379 } ) ;
380+
381+ vm. do_tick ( Duration :: ZERO ) ;
382+ vm. do_tick ( Duration :: ZERO ) ;
383+
384+ with_processor ( & mut vm, 0 , |p| {
385+ assert_eq ! ( p. state. variables[ "a" ] . get( & p. state) , LValue :: Number ( 1e308 ) ) ;
386+ assert_eq ! ( p. state. variables[ "b" ] . get( & p. state) , LValue :: Null ) ;
387+ assert_eq ! ( p. state. variables[ "c" ] . get( & p. state) , LValue :: Number ( -1e308 ) ) ;
388+ assert_eq ! ( p. state. variables[ "d" ] . get( & p. state) , LValue :: Null ) ;
389+ } ) ;
376390 }
377391
378392 #[ test]
@@ -810,4 +824,315 @@ mod tests {
810824 ) ;
811825 }
812826 }
827+
828+ #[ test]
829+ #[ allow( clippy:: approx_constant) ]
830+ fn test_op_unary ( ) {
831+ for ( op, x, want) in [
832+ // not
833+ ( "not" , "0b00" , ( -1 ) . into ( ) ) ,
834+ ( "not" , "0b01" , ( -2 ) . into ( ) ) ,
835+ ( "not" , "0b10" , ( -3 ) . into ( ) ) ,
836+ ( "not" , "0b11" , ( -4 ) . into ( ) ) ,
837+ ( "not" , "-1" , 0 . into ( ) ) ,
838+ ( "not" , "-2" , 1 . into ( ) ) ,
839+ ( "not" , "-3" , 2 . into ( ) ) ,
840+ ( "not" , "-4" , 3 . into ( ) ) ,
841+ // abs
842+ ( "abs" , "0" , 0 . into ( ) ) ,
843+ ( "abs" , "-0" , 0 . into ( ) ) ,
844+ ( "abs" , "1" , 1 . into ( ) ) ,
845+ ( "abs" , "-1" , 1 . into ( ) ) ,
846+ ( "abs" , "1e308" , 1e308 . into ( ) ) ,
847+ ( "abs" , "1e309" , 0 . into ( ) ) ,
848+ ( "abs" , "-1e308" , 1e308 . into ( ) ) ,
849+ ( "abs" , "-1e309" , 0 . into ( ) ) ,
850+ // sign
851+ ( "sign" , "0" , 0 . into ( ) ) ,
852+ ( "sign" , "-0" , 0 . into ( ) ) ,
853+ ( "sign" , "1" , 1 . into ( ) ) ,
854+ ( "sign" , "-1" , ( -1 ) . into ( ) ) ,
855+ ( "sign" , "1e308" , 1 . into ( ) ) ,
856+ ( "sign" , "1e309" , 0 . into ( ) ) ,
857+ ( "sign" , "-1e308" , ( -1 ) . into ( ) ) ,
858+ ( "sign" , "-1e309" , 0 . into ( ) ) ,
859+ // log
860+ ( "log" , "-1" , LValue :: Null ) ,
861+ ( "log" , "0" , LValue :: Null ) ,
862+ ( "log" , "@e" , 0.99999996963214 . into ( ) ) ,
863+ ( "log" , "2" , 0.6931471805599453 . into ( ) ) ,
864+ // log10
865+ ( "log10" , "-1" , LValue :: Null ) ,
866+ ( "log10" , "0" , LValue :: Null ) ,
867+ ( "log10" , "100" , 2 . into ( ) ) ,
868+ ( "log10" , "101" , 2.0043213737826426 . into ( ) ) ,
869+ // floor
870+ ( "floor" , "0" , 0 . into ( ) ) ,
871+ ( "floor" , "1" , 1 . into ( ) ) ,
872+ ( "floor" , "1.5" , 1 . into ( ) ) ,
873+ ( "floor" , "-1" , ( -1 ) . into ( ) ) ,
874+ ( "floor" , "-1.5" , ( -2 ) . into ( ) ) ,
875+ // ceil
876+ ( "ceil" , "0" , 0 . into ( ) ) ,
877+ ( "ceil" , "1" , 1 . into ( ) ) ,
878+ ( "ceil" , "1.5" , 2 . into ( ) ) ,
879+ ( "ceil" , "-1" , ( -1 ) . into ( ) ) ,
880+ ( "ceil" , "-1.5" , ( -1 ) . into ( ) ) ,
881+ // round
882+ ( "round" , "0" , 0 . into ( ) ) ,
883+ ( "round" , "1" , 1 . into ( ) ) ,
884+ ( "round" , "1.1" , 1 . into ( ) ) ,
885+ ( "round" , "1.49" , 1 . into ( ) ) ,
886+ ( "round" , "1.5" , 2 . into ( ) ) ,
887+ ( "round" , "1.51" , 2 . into ( ) ) ,
888+ ( "round" , "1.9" , 2 . into ( ) ) ,
889+ ( "round" , "-1" , ( -1 ) . into ( ) ) ,
890+ ( "round" , "-1.1" , ( -1 ) . into ( ) ) ,
891+ ( "round" , "-1.49" , ( -1 ) . into ( ) ) ,
892+ ( "round" , "-1.5" , ( -1 ) . into ( ) ) ,
893+ ( "round" , "-1.51" , ( -2 ) . into ( ) ) ,
894+ ( "round" , "-1.9" , ( -2 ) . into ( ) ) ,
895+ // sqrt
896+ ( "sqrt" , "-1" , LValue :: Null ) ,
897+ ( "sqrt" , "-0.25" , LValue :: Null ) ,
898+ ( "sqrt" , "0" , 0 . into ( ) ) ,
899+ ( "sqrt" , "0.25" , 0.5 . into ( ) ) ,
900+ ( "sqrt" , "1" , 1 . into ( ) ) ,
901+ ( "sqrt" , "4" , 2 . into ( ) ) ,
902+ // sin
903+ ( "sin" , "-30" , ( -0.49999999999999994 ) . into ( ) ) ,
904+ ( "sin" , "0" , 0 . into ( ) ) ,
905+ ( "sin" , "30" , 0.49999999999999994 . into ( ) ) ,
906+ ( "sin" , "45" , 0.7071067811865476 . into ( ) ) ,
907+ ( "sin" , "60" , 0.8660254037844386 . into ( ) ) ,
908+ ( "sin" , "90" , 1 . into ( ) ) ,
909+ ( "sin" , "180" , 1.2246467991473532e-16 . into ( ) ) ,
910+ // cos
911+ ( "cos" , "-30" , 0.8660254037844387 . into ( ) ) ,
912+ ( "cos" , "0" , 1 . into ( ) ) ,
913+ ( "cos" , "30" , 0.8660254037844387 . into ( ) ) ,
914+ ( "cos" , "45" , 0.7071067811865476 . into ( ) ) ,
915+ ( "cos" , "60" , 0.5000000000000001 . into ( ) ) ,
916+ ( "cos" , "90" , 6.123233995736766e-17 . into ( ) ) ,
917+ ( "cos" , "180" , ( -1 ) . into ( ) ) ,
918+ // tan
919+ ( "tan" , "0" , 0 . into ( ) ) ,
920+ ( "tan" , "45" , 0.9999999999999999 . into ( ) ) ,
921+ ( "tan" , "90" , 16331239353195370i64 . into ( ) ) ,
922+ ( "tan" , "91" , ( -57.28996163075955 ) . into ( ) ) ,
923+ // asin
924+ ( "asin" , "-0.5" , ( -30.000000000000004 ) . into ( ) ) ,
925+ ( "asin" , "0" , 0 . into ( ) ) ,
926+ ( "asin" , "0.5" , 30.000000000000004 . into ( ) ) ,
927+ // acos
928+ ( "acos" , "-0.5" , 120.00000000000001 . into ( ) ) ,
929+ ( "acos" , "0" , 90 . into ( ) ) ,
930+ ( "acos" , "0.5" , 60.00000000000001 . into ( ) ) ,
931+ // atan
932+ ( "atan" , "-0.5" , ( -26.56505117707799 ) . into ( ) ) ,
933+ ( "atan" , "0" , 0 . into ( ) ) ,
934+ ( "atan" , "0.5" , 26.56505117707799 . into ( ) ) ,
935+ ] {
936+ let mut vm = single_processor_vm (
937+ BlockType :: HyperProcessor ,
938+ & format ! (
939+ "
940+ op {op} got {x}
941+ stop
942+ "
943+ ) ,
944+ ) ;
945+
946+ run ( & mut vm, 1 , true ) ;
947+
948+ let state = take_processor ( & mut vm, 0 ) . state ;
949+ assert_eq ! ( state. variables[ "got" ] . get( & state) , want, "{op} {x}" ) ;
950+ }
951+ }
952+
953+ #[ test]
954+ fn test_op_binary ( ) {
955+ for ( op, x, y, want) in [
956+ // add
957+ ( "add" , "0" , "0" , 0 . into ( ) ) ,
958+ ( "add" , "0" , "1" , 1 . into ( ) ) ,
959+ ( "add" , "1.5" , "0.25" , 1.75 . into ( ) ) ,
960+ ( "add" , "1.0" , "-2.0" , ( -1 ) . into ( ) ) ,
961+ // sub
962+ ( "sub" , "3" , "1" , 2 . into ( ) ) ,
963+ ( "sub" , "3" , "-1" , 4 . into ( ) ) ,
964+ // mul
965+ ( "mul" , "1" , "0" , 0 . into ( ) ) ,
966+ ( "mul" , "1" , "1" , 1 . into ( ) ) ,
967+ ( "mul" , "3" , "-4.5" , ( -13.5 ) . into ( ) ) ,
968+ // div
969+ ( "div" , "5" , "2" , 2.5 . into ( ) ) ,
970+ ( "div" , "-5" , "2" , ( -2.5 ) . into ( ) ) ,
971+ ( "div" , "5" , "-2" , ( -2.5 ) . into ( ) ) ,
972+ ( "div" , "-5" , "-2" , 2.5 . into ( ) ) ,
973+ ( "div" , "1" , "0" , LValue :: Null ) ,
974+ ( "div" , "-1" , "0" , LValue :: Null ) ,
975+ ( "div" , "0" , "0" , LValue :: Null ) ,
976+ ( "div" , "0" , "1" , 0 . into ( ) ) ,
977+ ( "div" , "0" , "-1" , 0 . into ( ) ) ,
978+ // idiv
979+ ( "idiv" , "5" , "2" , 2 . into ( ) ) ,
980+ ( "idiv" , "-5" , "2" , ( -3 ) . into ( ) ) ,
981+ ( "idiv" , "5" , "-2" , ( -3 ) . into ( ) ) ,
982+ ( "idiv" , "-5" , "-2" , 2 . into ( ) ) ,
983+ ( "idiv" , "1" , "0" , LValue :: Null ) ,
984+ ( "idiv" , "-1" , "0" , LValue :: Null ) ,
985+ ( "idiv" , "0" , "0" , LValue :: Null ) ,
986+ ( "idiv" , "0" , "1" , 0 . into ( ) ) ,
987+ ( "idiv" , "0" , "-1" , 0 . into ( ) ) ,
988+ // mod
989+ ( "mod" , "5" , "2" , 1 . into ( ) ) ,
990+ ( "mod" , "-5" , "2" , ( -1 ) . into ( ) ) ,
991+ ( "mod" , "5" , "-2" , 1 . into ( ) ) ,
992+ ( "mod" , "-5" , "-2" , ( -1 ) . into ( ) ) ,
993+ // emod
994+ ( "emod" , "5" , "2" , 1 . into ( ) ) ,
995+ ( "emod" , "-5" , "2" , 1 . into ( ) ) ,
996+ ( "emod" , "5" , "-2" , ( -1 ) . into ( ) ) ,
997+ ( "emod" , "-5" , "-2" , ( -1 ) . into ( ) ) ,
998+ // pow
999+ ( "pow" , "3" , "2" , 9 . into ( ) ) ,
1000+ ( "pow" , "9" , "0.5" , 3 . into ( ) ) ,
1001+ ( "pow" , "16" , "-0.5" , 0.25 . into ( ) ) ,
1002+ ( "pow" , "-3" , "2" , 9 . into ( ) ) ,
1003+ ( "pow" , "-9" , "0.5" , LValue :: Null ) ,
1004+ ( "pow" , "-16" , "-0.5" , LValue :: Null ) ,
1005+ // land
1006+ ( "land" , "false" , "false" , 0 . into ( ) ) ,
1007+ ( "land" , "false" , "true" , 0 . into ( ) ) ,
1008+ ( "land" , "true" , "false" , 0 . into ( ) ) ,
1009+ ( "land" , "true" , "true" , 1 . into ( ) ) ,
1010+ ( "land" , "\" foo\" " , "null" , 0 . into ( ) ) ,
1011+ ( "land" , "\" foo\" " , "\" bar\" " , 1 . into ( ) ) ,
1012+ // shl
1013+ ( "shl" , "2" , "0" , 2 . into ( ) ) ,
1014+ ( "shl" , "2" , "1" , 4 . into ( ) ) ,
1015+ ( "shl" , "2" , "62" , ( -9223372036854775808i64 ) . into ( ) ) ,
1016+ ( "shl" , "2" , "63" , 0 . into ( ) ) ,
1017+ ( "shl" , "2" , "64" , 2 . into ( ) ) ,
1018+ ( "shl" , "2" , "-1" , 0 . into ( ) ) ,
1019+ ( "shl" , "2" , "-60" , 32 . into ( ) ) ,
1020+ ( "shl" , "-2" , "0" , ( -2 ) . into ( ) ) ,
1021+ ( "shl" , "-2" , "1" , ( -4 ) . into ( ) ) ,
1022+ ( "shl" , "-2" , "62" , ( -9223372036854775808i64 ) . into ( ) ) ,
1023+ ( "shl" , "-2" , "63" , 0 . into ( ) ) ,
1024+ ( "shl" , "-2" , "64" , ( -2 ) . into ( ) ) ,
1025+ ( "shl" , "-2" , "-1" , 0 . into ( ) ) ,
1026+ ( "shl" , "-2" , "-60" , ( -32 ) . into ( ) ) ,
1027+ // shr
1028+ ( "shr" , "2" , "0" , 2 . into ( ) ) ,
1029+ ( "shr" , "2" , "1" , 1 . into ( ) ) ,
1030+ ( "shr" , "2" , "62" , 0 . into ( ) ) ,
1031+ ( "shr" , "2" , "63" , 0 . into ( ) ) ,
1032+ ( "shr" , "2" , "64" , 2 . into ( ) ) ,
1033+ ( "shr" , "2" , "-1" , 0 . into ( ) ) ,
1034+ ( "shr" , "2" , "-60" , 0 . into ( ) ) ,
1035+ ( "shr" , "-2" , "0" , ( -2 ) . into ( ) ) ,
1036+ ( "shr" , "-2" , "1" , ( -1 ) . into ( ) ) ,
1037+ ( "shr" , "-2" , "62" , ( -1 ) . into ( ) ) ,
1038+ ( "shr" , "-2" , "63" , ( -1 ) . into ( ) ) ,
1039+ ( "shr" , "-2" , "64" , ( -2 ) . into ( ) ) ,
1040+ ( "shr" , "-2" , "-1" , ( -1 ) . into ( ) ) ,
1041+ ( "shr" , "-2" , "-60" , ( -1 ) . into ( ) ) ,
1042+ // ushr
1043+ ( "ushr" , "2" , "0" , 2 . into ( ) ) ,
1044+ ( "ushr" , "2" , "1" , 1 . into ( ) ) ,
1045+ ( "ushr" , "2" , "62" , 0 . into ( ) ) ,
1046+ ( "ushr" , "2" , "63" , 0 . into ( ) ) ,
1047+ ( "ushr" , "2" , "64" , 2 . into ( ) ) ,
1048+ ( "ushr" , "2" , "-1" , 0 . into ( ) ) ,
1049+ ( "ushr" , "2" , "-60" , 0 . into ( ) ) ,
1050+ ( "ushr" , "-2" , "0" , ( -2 ) . into ( ) ) ,
1051+ ( "ushr" , "-2" , "1" , 9223372036854775807i64 . into ( ) ) ,
1052+ ( "ushr" , "-2" , "62" , 3 . into ( ) ) ,
1053+ ( "ushr" , "-2" , "63" , 1 . into ( ) ) ,
1054+ ( "ushr" , "-2" , "64" , ( -2 ) . into ( ) ) ,
1055+ ( "ushr" , "-2" , "-1" , 1 . into ( ) ) ,
1056+ ( "ushr" , "-2" , "-60" , 1152921504606846976i64 . into ( ) ) ,
1057+ // or
1058+ ( "or" , "0b10" , "0b10" , 0b10 . into ( ) ) ,
1059+ ( "or" , "0b10" , "0b11" , 0b11 . into ( ) ) ,
1060+ ( "or" , "0b11" , "0b10" , 0b11 . into ( ) ) ,
1061+ ( "or" , "0b11" , "0b11" , 0b11 . into ( ) ) ,
1062+ ( "or" , "-1" , "0" , ( -1 ) . into ( ) ) ,
1063+ ( "or" , "-1" , "1" , ( -1 ) . into ( ) ) ,
1064+ // and
1065+ ( "and" , "0b10" , "0b10" , 0b10 . into ( ) ) ,
1066+ ( "and" , "0b10" , "0b11" , 0b10 . into ( ) ) ,
1067+ ( "and" , "0b11" , "0b10" , 0b10 . into ( ) ) ,
1068+ ( "and" , "0b11" , "0b11" , 0b11 . into ( ) ) ,
1069+ ( "and" , "-1" , "0" , 0 . into ( ) ) ,
1070+ ( "and" , "-1" , "1" , 1 . into ( ) ) ,
1071+ // xor
1072+ ( "xor" , "0b10" , "0b10" , 0b00 . into ( ) ) ,
1073+ ( "xor" , "0b10" , "0b11" , 0b01 . into ( ) ) ,
1074+ ( "xor" , "0b11" , "0b10" , 0b01 . into ( ) ) ,
1075+ ( "xor" , "0b11" , "0b11" , 0b00 . into ( ) ) ,
1076+ ( "xor" , "-1" , "0" , ( -1 ) . into ( ) ) ,
1077+ ( "xor" , "-1" , "1" , ( -2 ) . into ( ) ) ,
1078+ // max
1079+ ( "max" , "-1" , "1" , 1 . into ( ) ) ,
1080+ ( "max" , "1" , "-1" , 1 . into ( ) ) ,
1081+ ( "max" , "1" , "2" , 2 . into ( ) ) ,
1082+ ( "max" , "2" , "1" , 2 . into ( ) ) ,
1083+ // min
1084+ ( "min" , "-1" , "1" , ( -1 ) . into ( ) ) ,
1085+ ( "min" , "1" , "-1" , ( -1 ) . into ( ) ) ,
1086+ ( "min" , "1" , "2" , 1 . into ( ) ) ,
1087+ ( "min" , "2" , "1" , 1 . into ( ) ) ,
1088+ // angle
1089+ // mindustry apparently uses a different algorithm that gives 29.999948501586914 instead of 30
1090+ // but this is probably close enough
1091+ ( "angle" , "0.8660254038" , "0.5" , 30 . into ( ) ) ,
1092+ // angleDiff
1093+ ( "angleDiff" , "10" , "10" , 0 . into ( ) ) ,
1094+ ( "angleDiff" , "10" , "20" , 10 . into ( ) ) ,
1095+ ( "angleDiff" , "10" , "-10" , 20 . into ( ) ) ,
1096+ ( "angleDiff" , "10" , "350" , 20 . into ( ) ) ,
1097+ // len
1098+ ( "len" , "3" , "4" , 5 . into ( ) ) ,
1099+ ( "len" , "1" , "1" , 2f32 . sqrt ( ) . into ( ) ) ,
1100+ // noise
1101+ ( "noise" , "0" , "0" , 0 . into ( ) ) ,
1102+ // i'm not porting mindustry's noise algorithm. this is not the value you would get ingame
1103+ ( "noise" , "0" , "1" , ( -0.7139277281035279 ) . into ( ) ) ,
1104+ ( "noise" , "1" , "0" , ( -0.3646124062135936 ) . into ( ) ) ,
1105+ // logn
1106+ ( "logn" , "-1" , "2" , LValue :: Null ) ,
1107+ ( "logn" , "0" , "2" , LValue :: Null ) ,
1108+ ( "logn" , "0b1000" , "2" , 3 . into ( ) ) ,
1109+ ( "logn" , "0b1010" , "2" , 3.3219280948873626 . into ( ) ) ,
1110+ ( "logn" , "-1" , "10" , LValue :: Null ) ,
1111+ ( "logn" , "0" , "10" , LValue :: Null ) ,
1112+ ( "logn" , "100" , "10" , 2 . into ( ) ) ,
1113+ ( "logn" , "101" , "10" , 2.0043213737826426 . into ( ) ) ,
1114+ ]
1115+ . into_iter ( )
1116+ . chain (
1117+ CONDITION_TESTS
1118+ . iter ( )
1119+ . filter ( |& ( op, ..) | * op != "always" )
1120+ . map ( |& ( op, x, y, want) | ( op, x, y, want. into ( ) ) ) ,
1121+ ) {
1122+ let mut vm = single_processor_vm (
1123+ BlockType :: HyperProcessor ,
1124+ & format ! (
1125+ "
1126+ op {op} got {x} {y}
1127+ stop
1128+ "
1129+ ) ,
1130+ ) ;
1131+
1132+ run ( & mut vm, 1 , true ) ;
1133+
1134+ let state = take_processor ( & mut vm, 0 ) . state ;
1135+ assert_eq ! ( state. variables[ "got" ] . get( & state) , want, "{op} {x} {y}" ) ;
1136+ }
1137+ }
8131138}
0 commit comments