1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2000-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20-module(bs_match_misc_SUITE). 21 22-export([all/0, suite/0, 23 bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, 24 kenneth/1,encode_binary/1,native/1,happi/1, 25 size_var/1,wiger/1,x0_context/1,huge_float_field/1, 26 writable_binary_matched/1,otp_7198/1,unordered_bindings/1, 27 float_middle_endian/1,unsafe_get_binary_reuse/1, fp16/1]). 28 29-include_lib("common_test/include/ct.hrl"). 30 31suite() -> 32 [{ct_hooks,[ts_install_cth]}, 33 {timetrap, {seconds, 10}}]. 34 35all() -> 36 [bound_var, bound_tail, t_float, little_float, sean, 37 kenneth, encode_binary, native, happi, size_var, wiger, 38 x0_context, huge_float_field, writable_binary_matched, 39 otp_7198, unordered_bindings, float_middle_endian, 40 unsafe_get_binary_reuse, fp16]. 41 42 43%% Test matching of bound variables. 44bound_var(Config) when is_list(Config) -> 45 ok = bound_var(42, 13, <<42,13>>), 46 nope = bound_var(42, 13, <<42,255>>), 47 nope = bound_var(42, 13, <<154,255>>), 48 ok. 49 50bound_var(A, B, <<A:8,B:8>>) -> ok; 51bound_var(_, _, _) -> nope. 52 53%% Test matching of a bound tail. 54bound_tail(Config) when is_list(Config) -> 55 ok = bound_tail(<<>>, <<13,14>>), 56 ok = bound_tail(<<2,3>>, <<1,1,2,3>>), 57 nope = bound_tail(<<2,3>>, <<1,1,2,7>>), 58 nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), 59 nope = bound_tail(<<2,3>>, <<>>), 60 ok. 61 62bound_tail(T, <<_:16,T/binary>>) -> ok; 63bound_tail(_, _) -> nope. 64 65t_float(Config) when is_list(Config) -> 66 F = f1(), 67 G = f_one(), 68 69 G = match_float(<<63,128,0,0>>, 32, 0), 70 G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), 71 72 fcmp(F, match_float(<<F:32/float>>, 32, 0)), 73 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 74 fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), 75 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 76 fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), 77 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 78 79 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 8, 0)), 80 {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)), 81 82 ok. 83 84float_middle_endian(Config) when is_list(Config) -> 85 F = 9007199254740990.0, % turns to -NaN when word-swapped 86 fcmp(F, match_float(<<F:64/float>>, 64, 0)), 87 fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), 88 fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), 89 ok. 90 91 92fcmp(0.0, 0.0) -> ok; 93fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. 94 95match_float(Bin0, Fsz, I) -> 96 Bin = make_sub_bin(Bin0), 97 Bsz = size(Bin) * 8, 98 Tsz = Bsz - Fsz - I, 99 <<_:I,F:Fsz/float,_:Tsz>> = Bin, 100 F. 101 102little_float(Config) when is_list(Config) -> 103 F = f2(), 104 G = f_one(), 105 106 G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), 107 G = match_float_little(<<0,0,128,63>>, 32, 0), 108 109 fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), 110 fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), 111 fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), 112 fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), 113 fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), 114 fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), 115 116 ok. 117 118match_float_little(Bin0, Fsz, I) -> 119 Bin = make_sub_bin(Bin0), 120 Bsz = size(Bin) * 8, 121 Tsz = Bsz - Fsz - I, 122 <<_:I,F:Fsz/float-little,_:Tsz>> = Bin, 123 F. 124 125 126make_sub_bin(Bin0) -> 127 Sz = size(Bin0), 128 Bin1 = <<37,Bin0/binary,38,39>>, 129 <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1, 130 Bin. 131 132f1() -> 133 3.1415. 134 135f2() -> 136 2.7133. 137 138f_one() -> 139 1.0. 140 141sean(Config) when is_list(Config) -> 142 small = sean1(<<>>), 143 small = sean1(<<1>>), 144 small = sean1(<<1,2>>), 145 small = sean1(<<1,2,3>>), 146 large = sean1(<<1,2,3,4>>), 147 148 small = sean1(<<4>>), 149 small = sean1(<<4,5>>), 150 small = sean1(<<4,5,6>>), 151 {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), 152 ok. 153 154sean1(<<B/binary>>) when byte_size(B) < 4 -> small; 155sean1(<<1, _B/binary>>) -> large. 156 157kenneth(Config) when is_list(Config) -> 158 {ok,[145,148,113,129,0,0,0,0]} = 159 msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []). 160 161msisdn_internal_storage(<<>>,MSISDN) -> 162 {ok,lists:reverse(MSISDN)}; 163msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> 164 {ok,lists:reverse(MSISDN)}; 165msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when 166 DigitN < 10 -> 167 {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])}; 168msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when 169 DigitNplus1 < 10, 170 DigitN < 10 -> 171 NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN], 172 msisdn_internal_storage(Rest,NewMSISDN); 173msisdn_internal_storage(_Rest,_MSISDN) -> 174 {fault}. %% Mandatory IE incorrect 175 176encode_binary(Config) when is_list(Config) -> 177 "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []), 178 ok. 179 180encodeBinary(<<>>, Output) -> 181 lists:reverse(Output); 182encodeBinary(<<Data:1/binary>>, Output) -> 183 <<DChar1:6, DChar2:2>> = Data, 184 Char1 = getBase64Char(DChar1), 185 Char2 = getBase64Char(DChar2), 186 Char3 = "=", 187 Char4 = "=", 188 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 189 encodeBinary(<<>>, NewOutput); 190encodeBinary(<<Data:2/binary>>, Output) -> 191 <<DChar1:6, DChar2:6, DChar3:4>> = Data, 192 Char1 = getBase64Char(DChar1), 193 Char2 = getBase64Char(DChar2), 194 Char3 = getBase64Char(DChar3), 195 Char4 = "=", 196 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 197 encodeBinary(<<>>, NewOutput); 198encodeBinary(<<Data:3/binary, Rest/binary>>, Output) -> 199 <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data, 200 Char1 = getBase64Char(DChar1), 201 Char2 = getBase64Char(DChar2), 202 Char3 = getBase64Char(DChar3), 203 Char4 = getBase64Char(DChar4), 204 NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, 205 encodeBinary(Rest, NewOutput); 206encodeBinary(_Data, _) -> 207 error. 208 209getBase64Char(0) -> "A"; 210getBase64Char(1) -> "B"; 211getBase64Char(2) -> "C"; 212getBase64Char(3) -> "D"; 213getBase64Char(4) -> "E"; 214getBase64Char(5) -> "F"; 215getBase64Char(6) -> "G"; 216getBase64Char(7) -> "H"; 217getBase64Char(8) -> "I"; 218getBase64Char(9) -> "J"; 219getBase64Char(10) -> "K"; 220getBase64Char(11) -> "L"; 221getBase64Char(12) -> "M"; 222getBase64Char(13) -> "N"; 223getBase64Char(14) -> "O"; 224getBase64Char(15) -> "P"; 225getBase64Char(16) -> "Q"; 226getBase64Char(17) -> "R"; 227getBase64Char(18) -> "S"; 228getBase64Char(19) -> "T"; 229getBase64Char(20) -> "U"; 230getBase64Char(21) -> "V"; 231getBase64Char(22) -> "W"; 232getBase64Char(23) -> "X"; 233getBase64Char(24) -> "Y"; 234getBase64Char(25) -> "Z"; 235getBase64Char(26) -> "a"; 236getBase64Char(27) -> "b"; 237getBase64Char(28) -> "c"; 238getBase64Char(29) -> "d"; 239getBase64Char(30) -> "e"; 240getBase64Char(31) -> "f"; 241getBase64Char(32) -> "g"; 242getBase64Char(33) -> "h"; 243getBase64Char(34) -> "i"; 244getBase64Char(35) -> "j"; 245getBase64Char(36) -> "k"; 246getBase64Char(37) -> "l"; 247getBase64Char(38) -> "m"; 248getBase64Char(39) -> "n"; 249getBase64Char(40) -> "o"; 250getBase64Char(41) -> "p"; 251getBase64Char(42) -> "q"; 252getBase64Char(43) -> "r"; 253getBase64Char(44) -> "s"; 254getBase64Char(45) -> "t"; 255getBase64Char(46) -> "u"; 256getBase64Char(47) -> "v"; 257getBase64Char(48) -> "w"; 258getBase64Char(49) -> "x"; 259getBase64Char(50) -> "y"; 260getBase64Char(51) -> "z"; 261getBase64Char(52) -> "0"; 262getBase64Char(53) -> "1"; 263getBase64Char(54) -> "2"; 264getBase64Char(55) -> "3"; 265getBase64Char(56) -> "4"; 266getBase64Char(57) -> "5"; 267getBase64Char(58) -> "6"; 268getBase64Char(59) -> "7"; 269getBase64Char(60) -> "8"; 270getBase64Char(61) -> "9"; 271getBase64Char(62) -> "+"; 272getBase64Char(63) -> "/"; 273getBase64Char(_Else) -> 274 %% This is an illegal input. 275% cgLogEM:log(error, ?MODULE, getBase64Char, [Else], 276% "illegal input", 277% ?LINE, version()), 278 "**". 279 280-define(M(F), <<F>> = <<F>>). 281 282native(Config) when is_list(Config) -> 283 ?M(3.14:64/native-float), 284 ?M(333:16/native), 285 ?M(38658345:32/native), 286 case <<1:16/native>> of 287 <<0,1>> -> native_big(); 288 <<1,0>> -> native_little() 289 end. 290 291native_big() -> 292 <<37.33:64/native-float>> = <<37.33:64/big-float>>, 293 <<3974:16/native-integer>> = <<3974:16/big-integer>>, 294 {comment,"Big endian"}. 295 296native_little() -> 297 <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>, 298 <<7974:16/native-integer>> = <<7974:16/little-integer>>, 299 {comment,"Little endian"}. 300 301happi(Config) when is_list(Config) -> 302 Bin = <<".123">>, 303 <<"123">> = lex_digits1(Bin, 1, []), 304 <<"123">> = lex_digits2(Bin, 1, []), 305 ok. 306 307lex_digits1(<<$., Rest/binary>>,_Val,_Acc) -> 308 Rest; 309lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 310 lex_digits1(Rest,Val*10+dec(N),Acc); 311lex_digits1(_Other,_Val,_Acc) -> 312 not_ok. 313 314lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> 315 lex_digits2(Rest,Val*10+dec(N),Acc); 316lex_digits2(<<$., Rest/binary>>,_Val,_Acc) -> 317 Rest; 318lex_digits2(_Other,_Val,_Acc) -> 319 not_ok. 320 321dec(A) -> 322 A-$0. 323 324size_var(Config) when is_list(Config) -> 325 {<<45>>,<<>>} = split(<<1:16,45>>), 326 {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>), 327 {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>), 328 329 {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>), 330 331 {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>), 332 {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)), 333 334 <<"cdef">> = skip(<<2:8,"abcdef">>), 335 336 ok. 337 338split(<<N:16,B:N/binary,T/binary>>) -> 339 {B,T}. 340 341split(N, <<N:16,B:N/binary,T/binary>>) -> 342 {B,T}. 343 344split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) -> 345 {B,T}. 346 347skip(<<N:8,_:N/binary,T/binary>>) -> T. 348 349wiger(Config) when is_list(Config) -> 350 ok1 = wcheck(<<3>>), 351 ok2 = wcheck(<<1,2,3>>), 352 ok3 = wcheck(<<4>>), 353 {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), 354 {error,<<>>} = wcheck(<<>>), 355 ok. 356 357wcheck(<<A>>) when A==3-> 358 ok1; 359wcheck(<<_,_:2/binary>>) -> 360 ok2; 361wcheck(<<_>>) -> 362 ok3; 363wcheck(Other) -> 364 {error,Other}. 365 366%% Test that having the match context in x(0) works. 367 368x0_context(Config) when is_list(Config) -> 369 x0_0([], <<3.0:64/float,42:16,123456:32>>). 370 371x0_0(_, Bin) -> 372 <<3.0:64/float,42:16,_/binary>> = Bin, 373 x0_1([], Bin, 64, 16, 2). 374 375x0_1(_, Bin, FloatSz, IntSz, BinSz) -> 376 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin, 377 id({B,C,D}), 378 <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin, 379 x0_2([], Bin). 380 381x0_2(_, Bin) -> 382 <<_:64,0:7,42:9,_/binary>> = Bin, 383 x0_3([], Bin). 384 385x0_3(_, Bin) -> 386 case Bin of 387 <<_:72,7:8,_/binary>> -> 388 ct:fail(bs_matched_1); 389 <<_:64,0:16,_/binary>> -> 390 ct:fail(bs_matched_2); 391 <<_:64,42:16,123456:32,_/binary>> -> 392 ok 393 end. 394 395 396huge_float_field(Config) when is_list(Config) -> 397 Sz = 1 bsl 27, 398 Bin = <<0:Sz>>, 399 400 nomatch = overflow_huge_float_skip_32(Bin), 401 nomatch = overflow_huge_float_32(Bin), 402 403 ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 404 ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), 405 ok. 406 407overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32 408overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 409overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 410overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 411overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 412overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 413overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 414overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 415overflow_huge_float_skip_32(_) -> nomatch. 416 417overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32 418overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25 419overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26 420overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27 421overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28 422overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29 423overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30 424overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31 425overflow_huge_float_32(_) -> nomatch. 426 427 428overflow_huge_float(Bin, [Sz0|Sizes]) -> 429 Sz = id(1 bsl Sz0), 430 case Bin of 431 <<_:Sz/float-unit:8,0,_/binary>> -> 432 {error,Sz}; 433 _ -> 434 case Bin of 435 <<Var:Sz/float-unit:8,0,_/binary>> -> 436 {error,Sz,Var}; 437 _ -> 438 overflow_huge_float(Bin, Sizes) 439 end 440 end; 441overflow_huge_float(_, []) -> ok. 442 443overflow_huge_float_unit128(Bin, [Sz0|Sizes]) -> 444 Sz = id(1 bsl Sz0), 445 case Bin of 446 <<_:Sz/float-unit:128,0,_/binary>> -> 447 {error,Sz}; 448 _ -> 449 case Bin of 450 <<Var:Sz/float-unit:128,0,_/binary>> -> 451 {error,Sz,Var}; 452 _ -> 453 overflow_huge_float_unit128(Bin, Sizes) 454 end 455 end; 456overflow_huge_float_unit128(_, []) -> ok. 457 458 459%% 460%% Test that a writable binary can be safely matched. 461%% 462 463writable_binary_matched(Config) when is_list(Config) -> 464 WritableBin = create_writeable_binary(), 465 writable_binary_matched(WritableBin, WritableBin, 500). 466 467writable_binary_matched(<<0>>, _, N) -> 468 if N =:= 0 -> ok; 469 true -> 470 put(grow_heap, [N|get(grow_heap)]), 471 WritableBin = create_writeable_binary(), 472 writable_binary_matched(WritableBin, WritableBin, N-1) 473 end; 474writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) -> 475 WritableBin = writable_binary(WritableBin0, B), 476 writable_binary_matched(T, WritableBin, N). 477 478writable_binary(WritableBin0, B) when is_binary(WritableBin0) -> 479 %% Heavy append to force the binary to move. 480 WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>, 481 id(<<(id(0)):128/unit:8>>), 482 WritableBin. 483 484create_writeable_binary() -> 485 <<(id(<<>>))/binary,1,2,3,4,5,6,0>>. 486 487otp_7198(Config) when is_list(Config) -> 488 %% When a match context was reused, and grown at the same time to 489 %% increase the number of saved positions, the thing word was not updated 490 %% to account for the new size. Therefore, if there was a garbage collection, 491 %% the new slots would be included in the garbage collection. 492 [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)], 493 ok. 494 495do_otp_7198(FillerSize) -> 496 Filler = erlang:make_tuple(FillerSize, 42), 497 {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end), 498 receive 499 {'DOWN',Ref,process,Pid,normal} -> 500 ok; 501 {'DOWN',Ref,process,Pid,Reason} -> 502 ct:fail("unexpected: ~p", [Reason]) 503 end. 504 505do_otp_7198_test(_) -> 506 [{'KEYWORD',114}, 507 {'KEYWORD',101}, 508 {'KEYWORD',103}, 509 {'KEYWORD',105}, 510 {'KEYWORD',111}, 511 {'FIELD',110}, 512 {'KEYWORD',119}, 513 {'KEYWORD',104}, 514 {'KEYWORD',97}, 515 {'KEYWORD',116}, 516 {'KEYWORD',101}, 517 {'KEYWORD',118}, 518 {'KEYWORD',101}, 519 {'KEYWORD',114}, 520 '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []). 521 522 523otp_7198_scan(<<>>, TokAcc) -> 524 lists:reverse(['$thats_all_folks$' | TokAcc]); 525 526otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when 527 (D =:= $D orelse D =:= $d) and 528 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 529 otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]); 530 531otp_7198_scan(<<D>>, TokAcc) when 532 (D =:= $D) or (D =:= $d) -> 533 otp_7198_scan(<<>>, ['AND' | TokAcc]); 534 535otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when 536 (N =:= $N orelse N =:= $n) and 537 ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> 538 otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]); 539 540otp_7198_scan(<<C, Rest/binary>>, TokAcc) when 541 (C >= $A) and (C =< $Z); 542 (C >= $a) and (C =< $z); 543 (C >= $0) and (C =< $9) -> 544 case Rest of 545 <<$:, R/binary>> -> 546 otp_7198_scan(R, [{'FIELD', C} | TokAcc]); 547 _ -> 548 otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc]) 549 end. 550 551unordered_bindings(Config) when is_list(Config) -> 552 {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} = 553 unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>), 554 ok. 555 556unordered_bindings(CompressedLength, HashSize, PadLength, T) -> 557 <<Content:CompressedLength/binary,Mac:HashSize/binary, 558 Padding:PadLength/binary,PadLength>> = T, 559 {Content,Mac,Padding}. 560 561%% ERL-901: A load-time optimization assumed that match contexts had no further 562%% uses when a bs_get_binary2 overwrote the match context's register, and 563%% figured it would be safe to reuse the match context's memory for the 564%% resulting binary. 565%% 566%% This is no longer safe as of OTP 22, as a match context may be reused after 567%% being passed to another function. 568unsafe_get_binary_reuse(Config) when is_list(Config) -> 569 <<_First, Rest/binary>> = <<"hello">>, 570 ubgr_1(Rest), 571 <<Second,_/bits>> = Rest, 572 $e = Second, 573 ok. 574 575ubgr_1(<<_CP/utf8, Rest/binary>>) -> id(Rest); 576ubgr_1(_) -> false. 577 578id(I) -> I. 579 580-define(FP16(EncodedInt, Float), 581 (fun(NlInt, NlFloat) -> 582 <<F1:16/float>> = <<NlInt:16>>, 583 fcmp(F1, NlFloat), 584 <<F2:16/float>> = <<(NlInt+16#8000):16>>, 585 fcmp(F2, NlFloat), 586 <<F3:16/float-little>> = <<NlInt:16/little>>, 587 fcmp(F3, NlFloat), 588 <<F4:16/float-little>> = <<(NlInt+16#8000):16/little>>, 589 fcmp(F4, NlFloat), 590 <<F5:16/float-native>> = <<NlInt:16/native>>, 591 fcmp(F5, NlFloat), 592 <<F6:16/float-native>> = <<(NlInt+16#8000):16/native>>, 593 fcmp(F6, NlFloat) 594 end)(nonliteral(EncodedInt), nonliteral(Float)), 595 (fun() -> 596 <<F1:16/float>> = <<EncodedInt:16>>, 597 fcmp(F1, Float), 598 <<F2:16/float>> = <<(EncodedInt+16#8000):16>>, 599 fcmp(F2, Float), 600 <<F3:16/float-little>> = <<EncodedInt:16/little>>, 601 fcmp(F3, Float), 602 <<F4:16/float-little>> = <<(EncodedInt+16#8000):16/little>>, 603 fcmp(F4, Float), 604 <<F3:16/float-native>> = <<EncodedInt:16/native>>, 605 fcmp(F3, Float), 606 <<F4:16/float-native>> = <<(EncodedInt+16#8000):16/native>>, 607 fcmp(F4, Float) 608 end)()). 609 610nonliteral(X) -> X. 611 612fp16(_Config) -> 613 %% smallest positive subnormal number 614 ?FP16(16#0001, 0.000000059604645), 615 %% largest positive subnormal number 616 ?FP16(16#03ff, 0.000060975552), 617 %% smallest positive normal number 618 ?FP16(16#0400, 0.00006103515625), 619 %% largest normal number 620 ?FP16(16#7bff, 65504), 621 ?FP16(16#7bff, 65504.0), 622 %% largest number less than one 623 ?FP16(16#3bff, 0.99951172), 624 %% zero 625 ?FP16(16#0000, 0.0), 626 %% one 627 ?FP16(16#3c00, 1), 628 ?FP16(16#3c00, 1.0), 629 %% smallest number larger than one 630 ?FP16(16#3c01, 1.00097656), 631 %% rounding of 1/3 to nearest 632 ?FP16(16#3555, 0.33325195), 633 %% others 634 ?FP16(16#4000, 2), 635 ?FP16(16#4000, 2.0), 636 ok. 637