What's best way to do the following? Binary -> list -> binary seems unnecessary.
binary_and(A, B) ->
A2 = binary_to_list(A),
B2 = binary_to_list(B),
list_to_binary([U band V || {U, V} <- lists:zip(A2, B2)]).
What's best way to do the following? Binary -> list -> binary seems unnecessary.
binary_and(A, B) ->
A2 = binary_to_list(A),
B2 = binary_to_list(B),
list_to_binary([U band V || {U, V} <- lists:zip(A2, B2)]).
If don't care of performance, your code is absolutely OK. Otherwise you can do something different.
For example Erlang supports Integers of arbitrary size:
binary_and(A, B) ->
Size = bit_size(A),
<<X:Size>> = A,
<<Y:Size>> = B,
<<(X band Y):Size>>.
Or you can handcraft your own binary zip routine:
binary_and(A,B) -> binary_and(A, B, <<>>).
binary_and(<<A:8, RestA/bytes>>, <<B:8, RestB/bytes>>, Acc) ->
binary_add(RestA, RestB, <<Acc/bytes, (A band B):8>>);
binary_and(<<>>, <<>>, Result) -> Result.
Or optimized version:
binary_and(A,B) -> binary_and(A, B, <<>>).
binary_and(<<A:64, RestA/bytes>>, <<B:64, RestB/bytes>>, Acc) ->
binary_add(RestA, RestB, <<Acc/bytes, (A band B):64>>);
binary_and(<<A:32, RestA/bytes>>, <<B:32, RestB/bytes>>, Acc) ->
binary_add(RestA, RestB, <<Acc/bytes, (A band B):32>>);
binary_and(<<A:16, RestA/bytes>>, <<B:16, RestB/bytes>>, Acc) ->
binary_add(RestA, RestB, <<Acc/bytes, (A band B):16>>);
binary_and(<<A:8, RestA/bytes>>, <<B:8, RestB/bytes>>, Acc) ->
binary_add(RestA, RestB, <<Acc/bytes, (A band B):8>>);
binary_and(<<>>, <<>>, Result) -> Result.
or more sophistic
binary_and(A,B) -> binary_and({A, B}, 0, <<>>).
binary_and(Bins, Index, Acc) ->
case Bins of
{<<_:Index/bytes, A:64, _/bytes>>, <<_:Index/bytes, B:64, _/bytes>>} ->
binary_add(Bins, Index+8, <<Acc/bytes, (A band B):64>>);
{<<_:Index/bytes, A:32, _/bytes>>, <<_:Index/bytes, B:32, _/bytes>>} ->
binary_add(Bins, Index+4, <<Acc/bytes, (A band B):32>>);
{<<_:Index/bytes, A:16, _/bytes>>, <<_:Index/bytes, B:16, _/bytes>>} ->
binary_add(Bins, Index+2, <<Acc/bytes, (A band B):16>>);
{<<_:Index/bytes, A:8, _/bytes>>, <<_:Index/bytes, B:8, _/bytes>>} ->
binary_add(Bins, Index+1, <<Acc/bytes, (A band B):8>>);
{<<_:Index/bytes>>, <<_:Index/bytes>>} -> Acc
end.
Anyway you have to measure if you are really interested in performance. May be the first one is the fastest for your purposes.
If you want to see the power of the dark side...
binary_and(A, B) ->
Size = erlang:byte_size(A),
Size = erlang:byte_size(B),
Res = hipe_bifs:bytearray(Size, 0),
binary_and(Res, A, B, 0, Size).
binary_and(Res, _A, _B, Size, Size) ->
Res.
binary_and(Res, A, B, N, Size) ->
Bin = hipe_bifs:bytearray_sub(A, N) band hipe_bifs:bytearray_sub(B,N),
hipe_bifs:bytearray_update(Res, N, Bin),
binary_and(Res, A, B, N+1, Size).