LDA 2000h ; Store the no of byte that each number consists of in memory location 2000h.
MOV C A
MOV B A
LXI D 5000h
LXI H 2001h
STC
CMC
LOOP1: MOV A M
SHLD 7000h
LOOP: INX H
DCR C
JNZ LOOP
ADC M
STAX D
LHLD 7000h
LDA 2000h
MOV C A
INX D
INX H
DCR B
JNZ LOOP1
HLT
This is my code for the above mentioned problem. What would be more efficient algorithm to do so?
Related
I need to multiply two boolean matrices in Julia.
Doing simply A*A or A^2 returns an Int64 Matrix.
Is there a way how to multiply efficiently boolean matrices?
Following Oscar's comment of adding two for loops around your code, but without the LoopVectorization improvement, although with not allocating the full array inside the any call (so that the any stops on the first occurrence), this is decently fast (edit: replaced standard AND & with short-circuit &&):
function bool_mul2(A, B)
mA, nA = size(A)
mB, nB = size(B)
nA ≠ mB && error()
AB = BitArray(undef, mA, nB)
for i in 1:mA, j in 1:nB
AB[i,j] = any(A[i,k] && B[k,j] for k in 1:nA)
end
AB
end
(Note I removed the [ and ] inside the any to not allocate there.
E.g., with A and B of size 1000×1000, I get
julia> #btime bool_mul2($A, $B) ;
16.128 ms (3 allocations: 122.25 KiB)
compared to
julia> #btime bool_mul($A, $B) ;
346.374 ms (12 allocations: 7.75 MiB)
EDIT: For squaring the matrix, maybe try
function bool_square(A)
m, n = size(A)
m ≠ n && error()
A² = BitArray(undef, n, n)
for i in 1:n, j in 1:n
A²[i,j] = any(A[i,k] && A[k,j] for k in 1:n)
end
A²
end
for which I get
julia> A = rand(Bool, 500, 500) ;
julia> #btime $A * $A .!= 0 ;
42.483 ms (12 allocations: 1.94 MiB)
julia> #btime bool_square($A) ;
4.653 ms (3 allocations: 30.69 KiB)
One very simple solution is
function bool_mul(A,B)
return A*B .!= 0
end
This won't be the most efficient since it will allocate a matrix for A*B, but might end up being one of the fastest solutions available.
I have groups of scalars and two groups of vectors respertively:
w1, w2... wn
b1, b2... bn
c1, c2... cn
w1, w2... wn are scalars and stored in w,
b1, b2... bn stored in B and
c1, c2... cn stored in C. How efficiently get
w1*(b1*c1') + w2*(b2*c2') + ... + wn*(bn*cn')
Where bi and ci are vectors but bi*ci' is matrix, not a scalar?
Sizes: 1 x N for w, P x N for B and Q x N for C. wi = w(i), bi = B(:, i) and Ci = C(:, i)
Simply:
result = B*diag(W)*C';
If N is much bigger than P and Q, you might prefer to compute the weight matrix diag(W) in its sparse form with spdiags(W', 0, N, N) instead.
MVI B 07h
LXI H 0007h
LXI D 0007h
DCR B
LOOP1: DCR B
MOV C B
INR B
LOOP: DAD D
DCR C
JNZ LOOP
MOV E L
MOV D H
DCR B
JNZ LOOP1
HLT
I couldn't find out the problem in my code. Can you please help me out? It's giving me partially wrong answer. The two LSB bits are correct but not the MSBs.
I'm not sure why you're doing the extra decrement (followed by the increment) at the LOOP1 label to the B register but when B is one it causes C to become 0, which then wraps around to FFh and performs the multiply loop another 255 times.
Instead why don't you take out the DCR B / INR B and before the multiply loop just set the H register to 0. The full program would look like this:
MVI B, 07h
LXI H, 0007h
LXI D, 0007h
DCR B
LOOP1:
MOV C, B
LXI H, 0
LOOP:
DAD D
DCR C
JNZ LOOP
MOV E, L
MOV D, H
DCR B
JNZ LOOP1
HLT
In this piece of pseudocode from the MD5 Wikipedia website, fully available here, there is a pseudofunction leftrotate().
for each 512-bit chunk of message
break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
//Initialize hash value for this chunk:
var int A := a0
var int B := b0
var int C := c0
var int D := d0
//Main loop:
for i from 0 to 63
if 0 ≤ i ≤ 15 then
F := (B and C) or ((not B) and D)
g := i
else if 16 ≤ i ≤ 31
F := (D and B) or ((not D) and C)
g := (5×i + 1) mod 16
else if 32 ≤ i ≤ 47
F := B xor C xor D
g := (3×i + 5) mod 16
else if 48 ≤ i ≤ 63
F := C xor (B or (not D))
g := (7×i) mod 16
dTemp := D
D := C
C := B
B := B + leftrotate((A + F + K[i] + M[g]), s[i])
A := dTemp
end for
//Add this chunk's hash to result so far:
a0 := a0 + A
b0 := b0 + B
c0 := c0 + C
d0 := d0 + D
end for
var char digest[16] := a0 append b0 append c0 append d0 //(Output is in little-endian)
//leftrotate function definition
leftrotate (x, c)
return (x << c) binary or (x >> (32-c));
However, is the leftrotate() function a logical rotate or a circular rotate? As when I looked up the function on the bitwise operations wikipedia I saw different leftrotations. Which one does the MD5 hashfunction use?
The rotation is defined on the first Wikipedia as:
leftrotate (x, c)
return (x << c) binary or (x >> (32-c));
On RFC 1321 the function is formulated differently, like so:
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
Where s is the shift, but still I don't know what kind of leftrotate it is.
Found the answer while googling some other questions here
A bit rotation is also known as a circular shift rotation, extra information can be found here:
- Circular shift
- Bitwise operations
A circular shift shifts the numbers to left by an x amount, appending the extra ones back at the end.
Visit http://www.mapleprimes.com/questions/35644-Multiply-2-Matrices-In-Maple-Using-A-Procedure
restart:
mmm:=proc(a::Matrix,b::Matrix)
local c, i, j, k, m, n, p;
(m,n,p):=op([1,1],a), op([1,2],b), op([1,2],a);
if op([1,1],b) <> p then error "incompatible dimensions"; end if;
c:=Matrix(m,n);
for i from 1 to m do
for j from 1 to n do
c[i,j] := add(a[i,k]*b[k,j],k=1..p);
end do;
end do:
c;
end proc:
a:=LinearAlgebra:-RandomMatrix(2,3):
b:=LinearAlgebra:-RandomMatrix(3,5):
mmm(a,b);
a.b; # check
mmm(a,a^%T);
a.a^%T; # check
mmm(b,a); # test for dimension mismatch
b.a; # test for dimension mismatch
a:=LinearAlgebra:-RandomMatrix(33,33):
b:=LinearAlgebra:-RandomMatrix(33,33):
LinearAlgebra:-Norm(a.b - mmm(a,b));