Getting error from: dlen = uint32(0) ; - matlab
I don't know why but I am getting this error:
Error in mr_lsbpex (line 3)
dlen = uint32(0) ;
Output argument "a" (and maybe others) not assigned during call to "E:\path\mr_lsbpex.m>mr_lsbpex"
I have tested "dlen = uint32(0) ;" in matlab enviorment (outside of this function) and everything was OK. Here is my code:
function a = mr_lsbpex ( r, p )
% extract from an array
dlen = uint32(0) ;
s = size (r) ;
rnd = rand (s(1),s(2)) ;
rd = 32 ;
rl = s(2) ;
for i=1:s(2)
if rnd(1,i)<rd/rl
d = bitget (round(r(1,i)/p),1);
dlen = bitset (dlen,rd,d);
rd = rd -1 ;
end
rl = rl -1 ;
end
if (dlen > 10000000 )
clear a ;
return ;
end
a = uint8(zeros(dlen,1)) ;
rd = double(dlen * 8) ;
rl = double(s(1)*s(2)-s(2)) ;
for i=2:s(1)
for j=1:s(2)
if rnd(i,j)<rd/rl
d = bitget (round(r(i,j)/p) ,1) ;
a = z_set_bit (a,rd,d) ;
rd = rd - 1 ;
end
rl = rl - 1 ;
end
end
Remember: a needs to be returned ALLWAYS!
The error is not in that specific line, but in the "whole" function itself.
Your problem is that Matlab thinks that a its not going to be created. And actually in some case it may not be created.
The following line in the beginning of your function should do the trick
a=0; % well, or a=NaN; or whatever you want to return
Additionally, don't clear a in if (dlen > 10000000 ).
Related
QBasic/QB64: How to clean up an IF THEN IF "ladder"?
Not sure if I'm using the right terms here, but for whatever reason, QBasic doesn't understand something along the lines of "x = y = z". It's limited to two. To fix that, I did this: IF sum(1) = sum(2) THEN IF sum(2) = sum(3) THEN IF sum(3) = sum2(1) THEN IF sum2(1) = sum2(2) THEN IF sum2(2) = sum2(3) THEN IF sum2(3) = sum3 THEN IF sum3 = sum4 THEN PRINT "This is a Lo Shu Square, with all sums equaling"; sum(1) ELSE PRINT "This is not a Lo Shu Square." END IF END IF END IF END IF END IF END IF END IF END Definitely works, but something tells me there's a simpler way to have it check if all of the sums equal the same. Any suggestions?
It would work if all comparisons where put on one line separated by AND like this: REM code to shrink IFTHEN ladder: IF sum(1) = sum(2) AND sum(2) = sum(3) AND sum(3) = sum2(1) AND sum2(1) = sum2(2) AND sum2(2) = sum2(3) AND sum2(3) = sum3 AND sum3 = sum4 THEN PRINT "This is a Lo Shu Square, with all sums equaling"; sum(1) ELSE PRINT "This is not a Lo Shu Square." END IF END
You could also code the logic into a loop: DIM testvals(8) testvals(0) = sum(1) testvals(1) = sum(2) testvals(2) = sum(3) testvals(3) = sum2(1) testvals(4) = sum2(2) testvals(5) = sum2(3) testvals(6) = sum3 testvals(7) = sum4 DO FOR i = 1+LBOUND(testvals) TO UBOUND(testvals) IF testvals(i-1) <> testvals(i) THEN PRINT "This is not a Lo Shu square." EXIT DO END IF NEXT PRINT "This is a Lo Shu square, with all sums equaling"; sum(1) LOOP WHILE 1 = 0 This has a couple of benefits: It's easier to spot a typo if you change the code. You can always add and remove test values in similar cases. In this case, there's no need to do such a thing, but in some other cases, it may be beneficial to simply type testvals(8) = value and change the 8 to a 9 in the DIM line. It short-circuits the comparison, meaning if the first condition is false, it stops checking and says it's not a Lo Shu Square, similar to a tower of IF-THEN-ELSE statements (where every ELSE is PRINT "This is not a Lo Shu square.") QB64's AND operator evaluates both operands, even if the first operand is 0 or another "false" value. This can be much faster, though you likely won't notice a difference in this case. On the other hand, it does have some drawbacks: It's an unusual pattern in QB64 to not use AND in a case like this. In fact, this is one very good reason why AND exists. You can just as easily remove test values that are combined using AND with no need to renumber the items in the testvals array or change its dimensions. Even if you have many test values, it's often better to write a small program that generates the IF a AND b AND c AND ... THEN ... END IF block yourself (or something similar to your IF-THEN tower to retain short-circuit behavior) and paste the output into your program's code where it's needed.
A simpler way to check arrays: testvals(1) = sum(1) testvals(2) = sum(2) testvals(3) = sum(3) testvals(4) = sum2(1) testvals(5) = sum2(2) testvals(6) = sum2(3) testvals(7) = sum3 testvals(8) = sum4 FOR i = 1 TO 7 IF testvals(i) <> testvals(i + 1) THEN f = -1 EXIT FOR END IF NEXT IF f THEN PRINT "This is not a Lo Shu square." ELSE PRINT "This is a Lo Shu square, with all sums equaling"; sum(1) END IF
A simpler way to check a loop: testvals(1) = sum(1) testvals(2) = sum(2) testvals(3) = sum(3) testvals(4) = sum2(1) testvals(5) = sum2(2) testvals(6) = sum2(3) testvals(7) = sum3 testvals(8) = sum4 FOR i = 1 TO 7 IF testvals(i) <> testvals(i + 1) THEN PRINT "This is not a Lo Shu square." END END IF NEXT PRINT "This is a Lo Shu square, with all sums equaling"; sum(1)
Consolidate the logic into a function: FUNCTION isLoShuSquare (sums() AS DOUBLE) isLoShuSquare = 1 DIM i AS INTEGER FOR i = 0 TO UBOUND(sums) - 1 IF sums(i) <> sums(i + 1) THEN isLoShuSquare = 0 EXIT FOR END IF NEXT i END FUNCTION Then load the array and pass it to the function: DIM sums(7) AS DOUBLE DIM i AS INTEGER i = 0 sums(i) = sum(1): i = i + 1 sums(i) = sum(2): i = i + 1 sums(i) = sum(3): i = i + 1 sums(i) = sum2(1): i = i + 1 sums(i) = sum2(2): i = i + 1 sums(i) = sum2(3): i = i + 1 sums(i) = sum3: i = i + 1 sums(i) = sum4 PRINT isLoShuSquare(sums())
Another way to check an array in a loop in a function: DIM sums(8) AS DOUBLE sums(1) = sum(1) sums(2) = sum(2) sums(3) = sum(3) sums(4) = sum2(1) sums(5) = sum2(2) sums(6) = sum2(3) sums(7) = sum3 sums(8) = sum4 IF isLoShuSquare(sums()) = 0 THEN PRINT "This is not a Lo Shu square." ELSE PRINT "This is a Lo Shu square, with all sums equaling"; sum(1) END IF END FUNCTION isLoShuSquare (sums() AS DOUBLE) isLoShuSquare = -1 FOR i = 1 TO UBOUND(sums) - 1 IF sums(i) <> sums(i + 1) THEN isLoShuSquare = 0 EXIT FUNCTION END IF NEXT END FUNCTION
How can I modify a variable and it's corresponding dimension in a netcdf
I am running an idealized experiment with a atmospheric model with output in the format of netcdf. But the netcdf file header does not describe the variable and and dimension clearly. for example : netcdf qc3d { dimensions: Time = UNLIMITED ; // (1453 currently) bottom_top = 45 ; south_north = 32 ; west_east = 12288 ; variables: float Time(Time) ; Time:axis = "Time" ; Time:long_name = "Time" ; Time:standard_name = "Time" ; Time:units = "minutes since 1900-01-01 " ; double zc(bottom_top) ; zc:axis = "Z" ; zc:long_name = "vertical height of model layers, MSL" ; zc:standard_name = "altitude" ; zc:units = "m" ; zc:positive = "up" ; double yc(south_north) ; yc:axis = "Y" ; yc:long_name = "y-coordinate of grid cell centers in Cartesian system" ; yc:units = "m" ; double xc(west_east) ; xc:axis = "X" ; xc:long_name = "x-coordinate of grid cell centers in Cartesian system" ; xc:units = "m" ; float qc(Time, bottom_top, south_north, west_east) ; qc:long_name = "cloud water mixing ratio" ; qc:standard_name = "cloud_water_mixing" ; qc:units = "kg kg-1" ; qc:_FillValue = 9.96921e+36f ; qc:missing_value = 9.96921e+36f ; // global attributes: :model_tag = "CSU VVM" ; :references = "http://kiwi.atmos.colostate.edu/pubs/joon-hee-tech_report.pdf" ; :contact = "jung#atmos.colostate.edu" ; :institution = "Colorado State University" ; :VVM_casename = "GATE_PHASE_III " ; } there are 4 dimensions, Time(Time), zc(bottom_top), yc(south_north), xc(west_east) and 5 variable in which first 4 variables should be the dimension of the fifth variable, so called qc. But it seems not. The dimension is just a series number index from 1 to 45, 32 ...whatever else. I would like to calculate some variable which is the function of pressure. in the CDO the script is like this cdo expr,"pottemp=temp*((100000/clev(temp))^0.287);" ifile pottemp.nc (this code is from here) but I just obtain a series of index like 1 ,2 ,3 ... not the real pressure level when I use this function, clev(qv). So how can I rewrite the variable dimension like qc from qc(Time, bottom_top, south_north, west_east) ; to qc(Time, zc, yc, xc) ; I think it's possible for me to finish this in matlab, but I just don't want to open this dataset because it's size is too large... so I am trying to find some tools like ncks or cdo, but still failed to do this. thanks a lot.
With NCO try ncap2 -s 'pottemp=temp*((100000/zc)^0.287)' in.nc out.nc ncap2 documentation extending answer to cover additional question below: first use ncap2 to explicitly set zc to the values in the ascii file: ncap2 -s 'zc[$zc]={1.5,900,2500,3500}' in.nc out.nc (assuming zc is size 4 dimension). then define pottemp based on that zc.
VL_SIFT - Undefined function or variable
I try to make use of VLFeat library. So, I've downloaded the package and run vl_setup script. But when I create a new script and type this code: I = imread('imhog.jpg'); image(I) ; I = single(rgb2gray(I)) ; [f,d] = vl_sift(I) ; perm = randperm(size(f,2)) ; sel = perm(1:50) ; h1 = vl_plotframe(f(:,sel)) ; h2 = vl_plotframe(f(:,sel)) ; set(h1,'color','k','linewidth',3) ; set(h2,'color','y','linewidth',2) ; h3 = vl_plotsiftdescriptor(d(:,sel),f(:,sel)) ; set(h3,'color','g') ; it gives such error: vl_sift('imhog.jpg') Undefined function or variable 'vl_sift'.
MATLAB Execution Time Increasing
Here is my code. The intent is I have a Wireshark capture saved to a particularly formatted text file. The MATLAB code is supposed to go through the Packets, dissect them for different protocols, and then make tables based on those protocols. I currently have this programmed for ETHERNET/IP/UDP/MODBUS. In this case, it creates a column in MBTable each time it encounters a new register value, and each time it comes across a change to that register value, it updates the value in that line of the table. The first column of MBTable is time, the registers start with the second column. MBTable is preallocated to over 100,000 Rows (nol is very large), 10 columns before this code is executed. The actual data from a file I'm pulling into the table gets to about 10,000 rows and 4 columns and the code execution is so slow I have to stop it. The tic/toc value is calculated every 1000 rows and continues to increase exponentially with every iteration. It is a large loop, but I can't see where anything is growing in such a way that it would cause it to run slower with each iteration. All variables get initialized up top (left out to lessen amount of code. The variables eth, eth.ip, eth.ip.udp, and eth.ip.udp.modbus are all of type struct as is eth.header and eth.ip.header. WSID is a file ID from a .txt file opened earlier. MBTable = zeros(nol,10); tval = tic; while not(feof(WSID)) packline = packline + 1; fl = fl + 1; %Get the next line from the file MBLine = fgetl(WSID); %Make sure line is not blank or short if length(MBLine) >= 3 %Split the line into 1. Line no, 2. Data, 3. ASCII %MBAll = strsplit(MBLine,' '); %First line of new packet, if headers included if strcmp(MBLine(1:3),'No.') newpack = true; newtime = false; newdata = false; stoppack = false; packline = 1; end %If packet has headers, 2nd line contains timestamp if newpack Ordered = false; if packline == 2; newtime = true; %MBstrs = strsplit(MBAll{2},' '); packno = int32(str2double(MBLine(1:8))); t = str2double(MBLine(9:20)); et = t - lastt; if lastt > 0 && et > 0 L = L + 1; MBTable(L,1) = t; end %newpack = false; end if packline > 3 dataline = int16(str2double(MBLine(1:4))); packdata = strcat(packdata,MBLine(7:53)); end end else %if t >= st if packline > 3 stoppack = true; newpack = false; end if stoppack invalid = false; %eth = struct; eth.pack = packdata(~isspace(packdata)); eth.length = length(eth.pack); %Dissect the packet data eth.stbyte = 1; eth.ebyte = eth.length; eth.header.stbyte = 1; eth.header.ebyte = 28; %Ethernet Packet Data eth.header.pack = eth.pack(eth.stbyte:eth.stbyte+27); eth.header.dest = eth.header.pack(eth.header.stbyte:eth.header.stbyte + 11); eth.header.src = eth.header.pack(eth.header.stbyte + 12:eth.header.stbyte + 23); eth.typecode = eth.header.pack(eth.header.stbyte + 24:eth.header.ebyte); if strcmp(eth.typecode,'0800') eth.type = 'IP'; %eth.ip = struct; %IP Packet Data eth.ip.stbyte = eth.header.ebyte + 1; eth.ip.ver = eth.pack(eth.ip.stbyte); %IP Header length eth.ip.header.length = 4*int8(str2double(eth.pack(eth.ip.stbyte+1))); eth.ip.header.ebyte = eth.ip.stbyte + eth.ip.header.length - 1; %Differentiated Services Field eth.ip.DSF = eth.pack(eth.ip.stbyte + 2:eth.ip.stbyte + 3); %Total IP Packet Length eth.ip.length = hex2dec(eth.pack(eth.ip.stbyte+4:eth.ip.stbyte+7)); eth.ip.ebyte = eth.ip.stbyte + max(eth.ip.length,46) - 1; eth.ip.pack = eth.pack(eth.ip.stbyte:eth.ip.ebyte); eth.ip.ID = eth.pack(eth.ip.stbyte+8:eth.ip.stbyte+11); eth.ip.flags = eth.pack(eth.ip.stbyte+12:eth.ip.stbyte+13); eth.ip.fragoff = eth.pack(eth.ip.stbyte+14:eth.ip.stbyte+15); %Time to Live eth.ip.ttl = hex2dec(eth.pack(eth.ip.stbyte+16:eth.ip.stbyte+17)); eth.ip.typecode = eth.pack(eth.ip.stbyte+18:eth.ip.stbyte+19); eth.ip.checksum = eth.pack(eth.ip.stbyte+20:eth.ip.stbyte+23); %eth.ip.src = eth.pack(eth.ip.stbyte+24:eth.ip.stbyte+31); eth.ip.src = ... [num2str(hex2dec(eth.pack(eth.ip.stbyte+24:eth.ip.stbyte+25))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+26:eth.ip.stbyte+27))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+28:eth.ip.stbyte+29))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+30:eth.ip.stbyte+31)))]; eth.ip.dest = ... [num2str(hex2dec(eth.pack(eth.ip.stbyte+32:eth.ip.stbyte+33))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+34:eth.ip.stbyte+35))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+36:eth.ip.stbyte+37))),'.', ... num2str(hex2dec(eth.pack(eth.ip.stbyte+38:eth.ip.stbyte+39)))]; if strcmp(eth.ip.typecode,'11') eth.ip.type = 'UDP'; eth.ip.udp.stbyte = eth.ip.stbyte + 40; eth.ip.udp.src = hex2dec(eth.pack(eth.ip.udp.stbyte:eth.ip.udp.stbyte + 3)); eth.ip.udp.dest = hex2dec(eth.pack(eth.ip.udp.stbyte+4:eth.ip.udp.stbyte+7)); eth.ip.udp.length = hex2dec(eth.pack(eth.ip.udp.stbyte+8:eth.ip.udp.stbyte+11)); eth.ip.udp.checksum = eth.pack(eth.ip.udp.stbyte+12:eth.ip.udp.stbyte+15); eth.ip.udp.protoID = eth.pack(eth.ip.udp.stbyte+20:eth.ip.udp.stbyte+23); if strcmp(eth.ip.udp.protoID,'0000') eth.ip.udp.proto = 'MODBUS'; %eth.ip.udp.modbus = struct; eth.ip.udp.modbus.stbyte = eth.ip.udp.stbyte+16; eth.ip.udp.modbus.transID = eth.pack(eth.ip.udp.modbus.stbyte:eth.ip.udp.modbus.stbyte+3); eth.ip.udp.modbus.protoID = eth.ip.udp.protoID; eth.ip.udp.modbus.length = int16(str2double(eth.pack(eth.ip.udp.modbus.stbyte + 8:eth.ip.udp.modbus.stbyte + 11))); eth.ip.udp.modbus.UID = eth.pack(eth.ip.udp.modbus.stbyte + 12:eth.ip.udp.modbus.stbyte + 13); eth.ip.udp.modbus.func = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte + 14:eth.ip.udp.modbus.stbyte+15)); eth.ip.udp.modbus.register = eth.pack(eth.ip.udp.modbus.stbyte + 16: eth.ip.udp.modbus.stbyte+19); %Number of words to a register, or the number of registers eth.ip.udp.modbus.words = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte+20:eth.ip.udp.modbus.stbyte+23)); eth.ip.udp.modbus.bytes = hex2dec(eth.pack(eth.ip.udp.modbus.stbyte+24:eth.ip.udp.modbus.stbyte+25)); eth.ip.udp.modbus.data = eth.pack(eth.ip.udp.modbus.stbyte + 26:eth.ip.udp.modbus.stbyte + 26 + 2*eth.ip.udp.modbus.bytes - 1); %If func 16 or 23, loop through data/registers and add to table if eth.ip.udp.modbus.func == 16 || eth.ip.udp.modbus.func == 23 stp = eth.ip.udp.modbus.bytes*2/eth.ip.udp.modbus.words; for n = 1:stp:eth.ip.udp.modbus.bytes*2; %Check for existence of register as a key? if ~isKey(MBMap,eth.ip.udp.modbus.register) MBCol = MBCol + 1; MBMap(eth.ip.udp.modbus.register) = MBCol; end MBTable(L,MBCol) = hex2dec(eth.ip.udp.modbus.data(n:n+stp-1)); eth.ip.udp.modbus.register = dec2hex(hex2dec(eth.ip.udp.modbus.register)+1); end lastt = t; end %If func 4, make sure it is the response, then put %data into table for register column elseif false %need code to handle serial to UDP conversion box else invalid = true; end else invalid = true; end else invalid = true; end if ~invalid end end %end end %Display Progress if int64(fl/1000)*1000 == fl for x = 1:length(mess); fprintf('\b'); end %fprintf('Lines parsed: %i',fl); mess = sprintf('Lines parsed: %i / %i',fl,nol); fprintf('%s',mess); %Check execution time - getting slower: %%{ ext = toc(tval); mess = sprintf('\nExecution Time: %f\n',ext); fprintf('%s',mess); %%} end end ext = toc - exst; Update: I updated my code above to remove the overloaded operators (disp and lt were replaced with mess and lastt) Was asked to use the profiler, so I limited to 2000 lines in the table (added && L >=2000 to the while loop) to limit the execution time, and here are the top results from the profiler: SGAS_Wireshark_Parser_v0p7_fulleth 1 57.110 s 9.714 s Strcat 9187 29.271 s 13.598 s Blanks 9187 15.673 s 15.673 s Uigetfile 1 12.226 s 0.009 s uitools\private\uigetputfile_helper 1 12.212 s 0.031 s FileChooser.FileChooser>FileChooser.show 1 12.085 s 0.006s ...er>FileChooser.showPeerAndBlockMATLAB 1 12.056 s 0.001s ...nChooser>FileOpenChooser.doShowDialog 1 12.049 s 12.049 s hex2dec 44924 2.944 s 2.702 s num2str 16336 1.139 s 0.550 s str2double 17356 1.025 s 1.025 s int2str 16336 0.589 s 0.589 s fgetl 17356 0.488 s 0.488 s dec2hex 6126 0.304 s 0.304 s fliplr 44924 0.242 s 0.242 s It appears to be strcat calls that are doing it. I only explicitly call strcat on one line. Are some of the other string manipulations I'm doing calling strcat indirectly? Each loop should be calling strcat the same number of times though, so I still don't understand why it takes longer and longer the more it runs... also, hex2dec is called a lot, but is not really affecting the time. But anyway, are there any other methods I can use the combine the strings?
Here is the issue: The string (an char array in MATLAB) packdata was being resized and reallocated over and over again. That's what was slowing down this code. I did the following steps: I eliminated the redundant variable packdata and now only use eth.pack. I preallocated eth.pack and a couple "helper variables" of known lengths by running blanks ONCE for each before the loop ever starts eth.pack = blanks(604); thisline = blanks(47); smline = blanks(32); (Note: 604 is the maximum possible size of packdata based on headers + MODBUS protocol) Then I created a pointer variable to point to the location of the last char written to packdata. pptr = 1; ... dataline = int16(str2double(MBLine(1:4))); thisline = MBLine(7:53); %Always 47 characters smline = [thisline(~isspace(thisline)),blanks(32-sum(~isspace(thisline)))]; %Always 32 Characters eth.pack(pptr:pptr+31) = smline; pptr = pptr + 32; The above was inside the 'if packline > 3' block in place of the 'packdata =' statement, then at the end of the 'if stoppack' block was the reset statement: pptr = 1; %Reset Pointer FYI, not surprisingly this brought out other flaws in my code which I've mostly fixed but still need to finish. Not a big issue now as this loop executes lightning fast with these changes. Thanks to Yvon for helping point me in the right direction. I kept thinking my huge table, MBTable was the issue... but it had nothing to do with it.
Pure Lua implementation of md5
Is there a pure lua implementation of the md5 hashing algorithm? One that doesn't rely on any c or external libraries? There's javascript implementations that don't rely on c or anything, so it ought to be possible with lua. Thanks!
I combined the mentioned lua MD5 library that required bitlib and added in LuaBit to make it a pure lua implementation. As an additional benefit it's structured in such a way that it will work inside of the redis lua scripting environment. Please note that it is extremely slow compared to other non pure lua based implementations. --[[--------------- LuaBit v0.4 ------------------- a bitwise operation lib for lua. http://luaforge.net/projects/bit/ How to use: ------------------- bit.bnot(n) -- bitwise not (~n) bit.band(m, n) -- bitwise and (m & n) bit.bor(m, n) -- bitwise or (m | n) bit.bxor(m, n) -- bitwise xor (m ^ n) bit.brshift(n, bits) -- right shift (n >> bits) bit.blshift(n, bits) -- left shift (n << bits) bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>) Please note that bit.brshift and bit.blshift only support number within 32 bits. 2 utility functions are provided too: bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence) -- high bits first bit.tonumb(bit_tbl) -- convert a bit table into a number ------------------- Under the MIT license. copyright(c) 2006~2007 hanzhao (abrash_han#hotmail.com) --]]--------------- --do ------------------------ -- bit lib implementions local function check_int(n) -- checking not float if(n - math.floor(n) > 0) then error("trying to use bitwise operation on non-integer!") end end local function tbl_to_number(tbl) local n = #tbl local rslt = 0 local power = 1 for i = 1, n do rslt = rslt + tbl[i]*power power = power*2 end return rslt end local function expand(tbl_m, tbl_n) local big = {} local small = {} if(#tbl_m > #tbl_n) then big = tbl_m small = tbl_n else big = tbl_n small = tbl_m end -- expand small for i = #small + 1, #big do small[i] = 0 end end local to_bits = function () end local function bit_not(n) local tbl = to_bits(n) local size = math.max(#tbl, 32) for i = 1, size do if(tbl[i] == 1) then tbl[i] = 0 else tbl[i] = 1 end end return tbl_to_number(tbl) end to_bits = function (n) check_int(n) if(n < 0) then -- negative return to_bits(bit_not(math.abs(n)) + 1) end -- to bits table local tbl = {} local cnt = 1 while (n > 0) do local last = math.mod(n,2) if(last == 1) then tbl[cnt] = 1 else tbl[cnt] = 0 end n = (n-last)/2 cnt = cnt + 1 end return tbl end local function bit_or(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} local rslt = math.max(#tbl_m, #tbl_n) for i = 1, rslt do if(tbl_m[i]== 0 and tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl_to_number(tbl) end local function bit_and(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} local rslt = math.max(#tbl_m, #tbl_n) for i = 1, rslt do if(tbl_m[i]== 0 or tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl_to_number(tbl) end local function bit_xor(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} local rslt = math.max(#tbl_m, #tbl_n) for i = 1, rslt do if(tbl_m[i] ~= tbl_n[i]) then tbl[i] = 1 else tbl[i] = 0 end end --table.foreach(tbl, print) return tbl_to_number(tbl) end local function bit_rshift(n, bits) check_int(n) local high_bit = 0 if(n < 0) then -- negative n = bit_not(math.abs(n)) + 1 high_bit = 2147483648 -- 0x80000000 end for i=1, bits do n = n/2 n = bit_or(math.floor(n), high_bit) end return math.floor(n) end -- logic rightshift assures zero filling shift local function bit_logic_rshift(n, bits) check_int(n) if(n < 0) then -- negative n = bit_not(math.abs(n)) + 1 end for i=1, bits do n = n/2 end return math.floor(n) end local function bit_lshift(n, bits) check_int(n) if(n < 0) then -- negative n = bit_not(math.abs(n)) + 1 end for i=1, bits do n = n*2 end return bit_and(n, 4294967295) -- 0xFFFFFFFF end local function bit_xor2(m, n) local rhs = bit_or(bit_not(m), bit_not(n)) local lhs = bit_or(m, n) local rslt = bit_and(lhs, rhs) return rslt end -- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh) -- 10/02/2001 jcw#equi4.com local md5={ff=tonumber('ffffffff',16),consts={}} string.gsub([[ d76aa478 e8c7b756 242070db c1bdceee f57c0faf 4787c62a a8304613 fd469501 698098d8 8b44f7af ffff5bb1 895cd7be 6b901122 fd987193 a679438e 49b40821 f61e2562 c040b340 265e5a51 e9b6c7aa d62f105d 02441453 d8a1e681 e7d3fbc8 21e1cde6 c33707d6 f4d50d87 455a14ed a9e3e905 fcefa3f8 676f02d9 8d2a4c8a fffa3942 8771f681 6d9d6122 fde5380c a4beea44 4bdecfa9 f6bb4b60 bebfbc70 289b7ec6 eaa127fa d4ef3085 04881d05 d9d4d039 e6db99e5 1fa27cf8 c4ac5665 f4292244 432aff97 ab9423a7 fc93a039 655b59c3 8f0ccc92 ffeff47d 85845dd1 6fa87e4f fe2ce6e0 a3014314 4e0811a1 f7537e82 bd3af235 2ad7d2bb eb86d391 67452301 efcdab89 98badcfe 10325476 ]],"(%w+)", function (s) table.insert(md5.consts, tonumber(s,16)) end) --67452301 efcdab89 98badcfe 10325476 ]],"(%w+)", function (s) tinsert(md5.consts,tonumber(s,16)) end) function md5.transform(A,B,C,D,X) local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end local z=function (f,a,b,c,d,x,s,ac) a=bit_and(a+f(b,c,d)+x+ac,md5.ff) -- be *very* careful that left shift does not cause rounding! return bit_or(bit_lshift(bit_and(a,bit_rshift(md5.ff,s)),s),bit_rshift(a,32-s))+b end local a,b,c,d=A,B,C,D local t=md5.consts a=z(f,a,b,c,d,X[ 0], 7,t[ 1]) d=z(f,d,a,b,c,X[ 1],12,t[ 2]) c=z(f,c,d,a,b,X[ 2],17,t[ 3]) b=z(f,b,c,d,a,X[ 3],22,t[ 4]) a=z(f,a,b,c,d,X[ 4], 7,t[ 5]) d=z(f,d,a,b,c,X[ 5],12,t[ 6]) c=z(f,c,d,a,b,X[ 6],17,t[ 7]) b=z(f,b,c,d,a,X[ 7],22,t[ 8]) a=z(f,a,b,c,d,X[ 8], 7,t[ 9]) d=z(f,d,a,b,c,X[ 9],12,t[10]) c=z(f,c,d,a,b,X[10],17,t[11]) b=z(f,b,c,d,a,X[11],22,t[12]) a=z(f,a,b,c,d,X[12], 7,t[13]) d=z(f,d,a,b,c,X[13],12,t[14]) c=z(f,c,d,a,b,X[14],17,t[15]) b=z(f,b,c,d,a,X[15],22,t[16]) a=z(g,a,b,c,d,X[ 1], 5,t[17]) d=z(g,d,a,b,c,X[ 6], 9,t[18]) c=z(g,c,d,a,b,X[11],14,t[19]) b=z(g,b,c,d,a,X[ 0],20,t[20]) a=z(g,a,b,c,d,X[ 5], 5,t[21]) d=z(g,d,a,b,c,X[10], 9,t[22]) c=z(g,c,d,a,b,X[15],14,t[23]) b=z(g,b,c,d,a,X[ 4],20,t[24]) a=z(g,a,b,c,d,X[ 9], 5,t[25]) d=z(g,d,a,b,c,X[14], 9,t[26]) c=z(g,c,d,a,b,X[ 3],14,t[27]) b=z(g,b,c,d,a,X[ 8],20,t[28]) a=z(g,a,b,c,d,X[13], 5,t[29]) d=z(g,d,a,b,c,X[ 2], 9,t[30]) c=z(g,c,d,a,b,X[ 7],14,t[31]) b=z(g,b,c,d,a,X[12],20,t[32]) a=z(h,a,b,c,d,X[ 5], 4,t[33]) d=z(h,d,a,b,c,X[ 8],11,t[34]) c=z(h,c,d,a,b,X[11],16,t[35]) b=z(h,b,c,d,a,X[14],23,t[36]) a=z(h,a,b,c,d,X[ 1], 4,t[37]) d=z(h,d,a,b,c,X[ 4],11,t[38]) c=z(h,c,d,a,b,X[ 7],16,t[39]) b=z(h,b,c,d,a,X[10],23,t[40]) a=z(h,a,b,c,d,X[13], 4,t[41]) d=z(h,d,a,b,c,X[ 0],11,t[42]) c=z(h,c,d,a,b,X[ 3],16,t[43]) b=z(h,b,c,d,a,X[ 6],23,t[44]) a=z(h,a,b,c,d,X[ 9], 4,t[45]) d=z(h,d,a,b,c,X[12],11,t[46]) c=z(h,c,d,a,b,X[15],16,t[47]) b=z(h,b,c,d,a,X[ 2],23,t[48]) a=z(i,a,b,c,d,X[ 0], 6,t[49]) d=z(i,d,a,b,c,X[ 7],10,t[50]) c=z(i,c,d,a,b,X[14],15,t[51]) b=z(i,b,c,d,a,X[ 5],21,t[52]) a=z(i,a,b,c,d,X[12], 6,t[53]) d=z(i,d,a,b,c,X[ 3],10,t[54]) c=z(i,c,d,a,b,X[10],15,t[55]) b=z(i,b,c,d,a,X[ 1],21,t[56]) a=z(i,a,b,c,d,X[ 8], 6,t[57]) d=z(i,d,a,b,c,X[15],10,t[58]) c=z(i,c,d,a,b,X[ 6],15,t[59]) b=z(i,b,c,d,a,X[13],21,t[60]) a=z(i,a,b,c,d,X[ 4], 6,t[61]) d=z(i,d,a,b,c,X[11],10,t[62]) c=z(i,c,d,a,b,X[ 2],15,t[63]) b=z(i,b,c,d,a,X[ 9],21,t[64]) return A+a,B+b,C+c,D+d end -- convert little-endian 32-bit int to a 4-char string local function leIstr(i) local f=function (s) return string.char(bit_and(bit_rshift(i,s),255)) end return f(0)..f(8)..f(16)..f(24) end -- convert raw string to big-endian int local function beInt(s) local v=0 for i=1,string.len(s) do v=v*256+string.byte(s,i) end return v end -- convert raw string to little-endian int local function leInt(s) local v=0 for i=string.len(s),1,-1 do v=v*256+string.byte(s,i) end return v end -- cut up a string in little-endian ints of given size local function leStrCuts(s,...) local o,r=1,{} for i=1,#arg do table.insert(r,leInt(string.sub(s,o,o+arg[i]-1))) o=o+arg[i] end return r end function md5.Calc(s) local msgLen=string.len(s) local padLen=56- msgLen % 64 if msgLen % 64 > 56 then padLen=padLen+64 end if padLen==0 then padLen=64 end s=s..string.char(128)..string.rep(string.char(0),padLen-1) s=s..leIstr(8*msgLen)..leIstr(0) assert(string.len(s) % 64 ==0) local t=md5.consts local a,b,c,d=t[65],t[66],t[67],t[68] for i=1,string.len(s),64 do local X=leStrCuts(string.sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) assert(#X==16) X[0]=table.remove(X,1) -- zero based! a,b,c,d=md5.transform(a,b,c,d,X) end local swap=function (w) return beInt(leIstr(w)) end return string.format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d)) end return md5.Calc("asdf"); -- 912ec803b2ce49e4a541068d495ab570 It is available in this gist.
http://equi4.com/md5/md5calc.lua but that still requires a lib.
There's an old one here but it requires bitlib.
I've refined #Adam Baldwin's solution and made a library that calculates md5 sums in pure Lua, with no external dependencies and no C: https://github.com/kikito/md5.lua Summary of changes: Implemented two functions on the interface, md5.sum and md5.sumhex, that work exactly like their counterparts in the Kepler library, but are implemented in Lua alone. Added a small test suite with using busted. Removed some unused functions Avoided re-creation of anonymous functions when it was not needed Simplified the creation of the constants, and made them private Spacing and naming changes. For now I don't need md5.crypt and md5.decrypt, so I have not implemented those. But I will accept pull requests :)