I have a function that is meant to dynamically change the size of a 3D Array or table but it keeps breaking saying that it return value nil because it is out of bounds. Here is the code for it:
function resize()
temp = { }
for h=1, height do
table.insert( temp , { } )
for y=1, length do
table.insert ( temp[h], { } )
for x=1, width do
num = 16
if #blocks <= height then
if #blocks[h] <= length then
if #blocks[h][y] <= width then
num = blocks[h][y][x]
end
end
end
table.insert( temp[h][y] , num )
end
end
end
blocks = temp
end
I know it's not very well commented but the idea is that it creates a new table with the changed dimensions, and then superimpose the data of blocks over the new table and finally overwriting blocks with the new temp table.
The length width and height are changed by one either incremented or decremented but only one at a time.
I'm not sure if I explained it clearly enough, if not let me know and I'll try explain in more detail.
Thanks all,
James
I think that the bug lies in your if statements. You should sizes of blocks against h, y and x, not height and length and width.
As a side note, do not use table.insert when you can substitute it with temp[h] = {}. It's faster. Also, try to use locals for temp storage.
Your specific error (probably)
You do not test against nil values. Any non-initialized table (= array in this case) members are nil by definition. And comparing nil with a number will generate an error:
lua: attempt to compare nil with number
However, as you seem unable to provide the actual error message, this is only a guess. Do not take me wrong these are errors in your code, but there could be something else wrong that I overlooked. Anyway here are some comments along with your code to show you what happens
if #blocks <= height then -- say #blocks is 3, height is 4
if #blocks[h] <= length then -- E: in iteration 4 blocks[h] is nil
if #blocks[h][y] <= width then -- E: in it. 3,4 blocks[h][y] is nil
num = blocks[h][y][x]
end
end
end
You would have to test against nil on every level first, like
if blocks[h] and blocks[h][y] and blocks[h][y][x] and
#blocks[h]<=height and #blocks[h][y]<=height and #blocks[h][y][x]<=height
num = blocks[h][y][x]
end
General programming mistakes
blocks, length, width and height seem to be parameters for your function but are not in its header, so I suppose you set them externally before calling the function? This is certainly not good practice.
temp and num should be declared local.
Alternative
You can make the data-structure more intelligent, for example, if you put your 3D array in a flattened table and add a __call metamethod like this
function newMdArray(X, Y, Z)
local MT = { __call = function(t, x, y, z, v)
if x>X or y>Y or z>Z or x<1 or y<1 or z<1 then return nil end
local k = x + X*(y-1) + X*Y*(z-1);
if v ~= nil then t[k] = v; end
return t[k]
end };
return setmetatable({}, MT);
end
Then this is all you have to do to make a resized copy of it:
function resizeMdArray(array, X, Y, Z)
local r = newMdArray(X, Y, Z);
for x=1, X do
for y=1, Y do
for z=1, Z do
r(x, y, z, array(x, y, z) or 16);
end
end
end
return r;
end
A nice bonus is, since this data structure flattens the 3D array into a 1D array, if you only want to copy the data, you can do so by simply accessing it as a table and copying each element:
for i=1, X*Y*Z do
new[i] = old[i]
end
Of course you could do the very same with a "real" (hidden) 3-D array in the background saving you the arithmetic calculations, however then you would have to test for empty values all the time to prevent nil errors.
Well I'm not sure if this is the best way to do it, but it does work.
function resize()
temp = { } -- temp table
-- inserting all the height levels
for h=1, height do table.insert( temp , { } ) end
-- inserting all the lengths
for h=1, height do
for l=1, length do table.insert( temp[h], { } ) end
end
-- inserting all the width and defaulting them to 0
for h=1, height do
for l=1, length do
for w=1, width do table.insert( temp[h][l] , 0 ) end
end
end
-- if the canvas size is increasing
if #blocks <= height then
if #blocks[1] <= length then
if #blocks[1][1] <= width then
for h=1, #blocks do
for l=1, #blocks[1] do
for w=1, #blocks[1][1] do
-- fill in data from blocks
temp[h][l][w] = blocks[h][l][w]
end
end
end
end
end
end
--if the canvas size is decreasing
if #blocks >= height then
if #blocks[1] >= length then
if #blocks[1][1] >= width then
for h=1, #temp do
for l=1, #temp[1] do
for w=1, #temp[1][1] do
-- fill in data from blocks but not the last value
temp[h][l][w] = blocks[h][l][w]
end
end
end
end
end
end
-- overwrite blocks with the new dimensions
blocks = temp
Related
I'm currently learning about recursion, it's pretty hard to understand. I found a very common example for it:
function factorial(N)
local Value
if N == 0 then
Value = 1
else
Value = N * factorial(N - 1)
end
return Value
end
print(factorial(3))
N == 0 is the base case. But when i changed it into N == 1, the result is still remains the same. (it will print 6).
Is using the base case important? (will it break or something?)
What's the difference between using N == 0 (base case) and N == 1?
That's just a coincidence, since 1 * 1 = 1, so it ends up working either way.
But consider the edge-case where N = 0, if you check for N == 1, then you'd go into the else branch and calculate 0 * factorial(-1), which would lead to an endless loop.
The same would happen in both cases if you just called factorial(-1) directly, which is why you should either check for > 0 instead (effectively treating every negative value as 0 and returning 1, or add another if condition and raise an error when N is negative.
EDIT: As pointed out in another answer, your implementation is not tail-recursive, meaning it accumulates memory for every recursive functioncall until it finishes or runs out of memory.
You can make the function tail-recursive, which allows Lua to treat it pretty much like a normal loop that could run as long as it takes to calculate its result:
local function factorial(n, acc)
acc = acc or 1
if n <= 0 then
return acc
else
return factorial(n-1, acc*n)
end
return Value
end
print(factorial(3))
Note though, that in the case of factorial, it would take you way longer to run out of stack memory than to overflow Luas number data type at around 21!, so making it tail-recursive is really just a matter of training yourself to write better code.
As the above answer and comments have pointed out, it is essential to have a base-case in a recursive function; otherwise, one ends up with an infinite loop.
Also, in the case of your factorial function, it is probably more efficient to use a helper function to perform the recursion, so as to take advantage of Lua's tail-call optimizations. Since Lua conveniently allows for local functions, you can define a helper within the scope of your factorial function.
Note that this example is not meant to handle the factorials of negative numbers.
-- Requires: n is an integer greater than or equal to 0.
-- Effects : returns the factorial of n.
function fact(n)
-- Local function that will actually perform the recursion.
local function fact_helper(n, i)
-- This is the base case.
if (i == 1) then
return n
end
-- Take advantage of tail calls.
return fact_helper(n * i, i - 1)
end
-- Check for edge cases, such as fact(0) and fact(1).
if ((n == 0) or (n == 1)) then
return 1
end
return fact_helper(n, n - 1)
end
I have the following code in Octave for implementing the composite trapezoid rule and for some reason the function only stalls whenever I execute it in Octave on f = #(x) x^2, a = 0, b = 4, TOL = 10^-6. Whenever I call trapezoid(f, a, b, TOL), nothing happens and I have to exit the Terminal in order to do anything else in Octave. Here is the code:
% INPUTS
%
% f : a function
% a : starting point
% b : endpoint
% TOL : tolerance
function root = trapezoid(f, a, b, TOL)
disp('test');
max_iterations = 10000;
disp(max_iterations);
count = 1;
disp(count);
initial = (b-a)*(f(b) + f(a))/2;
while count < max_iterations
disp(initial);
trap_0 = initial;
trap_1 = 0;
trap_1_midpoints = a:(0.5^count):b;
for i = 1:(length(trap_1_midpoints)-1)
trap_1 = trap_1 + (trap_1_midpoints(i+1) - trap_1_midpoints(i))*(f(trap_1_midpoints(i+1) + f(trap_1_midpoints(i))))/2;
endfor
if abs(trap_0 - trap_1) < TOL
root = trap_1;
return;
endif
intial = trap_1;
count = count + 1;
disp(count);
endwhile
disp(['Process ended after ' num2str(max_iterations), ' iterations.']);
I have tried your function in Matlab.
Your code is not stalling. It is rather that the size of trap_1_midpoints increases exponentionaly. With that the computation time of trap_1 increases also exponentionaly. This is what you experience as stalling.
I also found a possible bug in your code. I guess the line after the if clause should be initial = trap_1. Check the missing 'i'.
With that, your code still takes forever, but if you increase the tolerance (e.g. to a value of 1) your code return.
You could try to vectorize the for loop for speed up.
Edit: I think inside your for loop, a ) is missing after f(trap_1_midpoints(i+1).
After count=52 or so, the arithmetic sequence trap_1_midpoints is no longer representable in any meaningful fashion in floating point numbers. After count=1075 or similar, the step size is no longer representable as a positive floating point double number. That all is to say, the bound max_iterations = 10000 is ludicrous. As explained below, all computations after count=20 are meaningless.
The theoretical error for stepsize h is O(T·h^2). There is a numerical error accumulation in the summation of O(T/h) numbers that is of that size, i.e., O(mu/h) with mu=1ulp=2^(-52). Which in total means that the lowest error of the numerical integration can be expected around h=mu^(1/3), for double numbers thus h=1e-5 or in the algorithm count=17. This may vary with interval length and how smooth or wavy the function is.
One can expect the behavior that the error divides by four while halving the step size only for step sizes above this boundary 1e-5. This also means that abs(trap_0 - trap_1) is a reliable measure for the error of trap_0 (and abs(trap_0 - trap_1)/3 for trap_1) only inside this range of step sizes.
The error bound TOL=1e-6 should be met for about h=1e-3, which corresponds to count=10. If the recursion does not stop for count = 14 (which should give an error smaller than 1e-8) then the method is not accurately implemented.
Currently I'm having trouble creating multiple format in SSRS for one Axis. The current situation is that I have a measure that could bring a maximum value of 1.2M (Currency) but an average of 500K depending the period. Originally I have the labelformat property set to 0,,M, but this doesn't bring the correct scale when the value is less than a million.
This are the current solution I have tried:
=IIF(Sum(Fields!Current_Year.Value, "CustomerSales") > Sum(Fields!Last_Year.Value, "CustomerSales"),
IIF(Sum(Fields!Current_Year.Value, "CustomerSales") < 1000000, "0,K", "0,,M"),
IIF(Sum(Fields!Last_Year.Value, "CustomerSales") < 1000000, "0,K", "0,,M"))
Public Function LabelCustomFormat(ByVal CY As Integer, ByVal LY As Integer) As String
If CY > LY Then
If(CY < 1000000) THEN
Return "0,K"
Else
Return "0,,M"
End If
Else
IF(LY < 1000000) THEN
Return "0,K"
Else
Return "0,,M"
End If
End If
End Function
Is it possible to have the different scale in one Axis of a Chart? If so, please help.
Well after trying to make a dynamic scale in the axis without success, I left the label format with the expression 0,,M and set the interval to a 1M instead of 500K.
I'm trying to compute the Fourier coefficients for a waveform using MATLAB. The coefficients can be computed using the following formulas:
T is chosen to be 1 which gives omega = 2pi.
However I'm having issues performing the integrals. The functions are are triangle wave (Which can be generated using sawtooth(t,0.5) if I'm not mistaking) as well as a square wave.
I've tried with the following code (For the triangle wave):
function [ a0,am,bm ] = test( numTerms )
b_m = zeros(1,numTerms);
w=2*pi;
for i = 1:numTerms
f1 = #(t) sawtooth(t,0.5).*cos(i*w*t);
f2 = #(t) sawtooth(t,0.5).*sin(i*w*t);
am(i) = 2*quad(f1,0,1);
bm(i) = 2*quad(f2,0,1);
end
end
However it's not getting anywhere near the values I need. The b_m coefficients are given for a
triangle wave and are supposed to be 1/m^2 and -1/m^2 when m is odd alternating beginning with the positive term.
The major issue for me is that I don't quite understand how integrals work in MATLAB and I'm not sure whether or not the approach I've chosen works.
Edit:
To clairify, this is the form that I'm looking to write the function on when the coefficients have been determined:
Here's an attempt using fft:
function [ a0,am,bm ] = test( numTerms )
T=2*pi;
w=1;
t = [0:0.1:2];
f = fft(sawtooth(t,0.5));
am = real(f);
bm = imag(f);
func = num2str(f(1));
for i = 1:numTerms
func = strcat(func,'+',num2str(am(i)),'*cos(',num2str(i*w),'*t)','+',num2str(bm(i)),'*sin(',num2str(i*w),'*t)');
end
y = inline(func);
plot(t,y(t));
end
Looks to me that your problem is what sawtooth returns the mathworks documentation says that:
sawtooth(t,width) generates a modified triangle wave where width, a scalar parameter between 0 and 1, determines the point between 0 and 2π at which the maximum occurs. The function increases from -1 to 1 on the interval 0 to 2πwidth, then decreases linearly from 1 to -1 on the interval 2πwidth to 2π. Thus a parameter of 0.5 specifies a standard triangle wave, symmetric about time instant π with peak-to-peak amplitude of 1. sawtooth(t,1) is equivalent to sawtooth(t).
So I'm guessing that's part of your problem.
After you responded I looked into it some more. Looks to me like it's the quad function; not very accurate! I recast the problem like this:
function [ a0,am,bm ] = sotest( t, numTerms )
bm = zeros(1,numTerms);
am = zeros(1,numTerms);
% 2L = 1
L = 0.5;
for ii = 1:numTerms
am(ii) = (1/L)*quadl(#(x) aCos(x,ii,L),0,2*L);
bm(ii) = (1/L)*quadl(#(x) aSin(x,ii,L),0,2*L);
end
ii = 0;
a0 = (1/L)*trapz( t, t.*cos((ii*pi*t)/L) );
% now let's test it
y = ones(size(t))*(a0/2);
for ii=1:numTerms
y = y + am(ii)*cos(ii*2*pi*t);
y = y + bm(ii)*sin(ii*2*pi*t);
end
figure; plot( t, y);
end
function a = aCos(t,n,L)
a = t.*cos((n*pi*t)/L);
end
function b = aSin(t,n,L)
b = t.*sin((n*pi*t)/L);
end
And then I called it like:
[ a0,am,bm ] = sotest( t, 100 );
and I got:
Sweetness!!!
All I really changed was from quad to quadl. I figured that out by using trapz which worked great until the time vector I was using didn't have enough resolution, which led me to believe it was a numerical issue rather than something fundamental. Hope this helps!
To troubleshoot your code I would plot the functions you are using and investigate, how the quad function samples them. You might be undersampling them, so make sure your minimum step size is smaller than the period of the function by at least factor 10.
I would suggest using the FFTs that are built-in to Matlab. Not only is the FFT the most efficient method to compute a spectrum (it is n*log(n) dependent on the length n of the array, whereas the integral in n^2 dependent), it will also give you automatically the frequency points that are supported by your (equally spaced) time data. If you compute the integral yourself (might be needed if datapoints are not equally spaced), you might calculate frequency data that are not resolved (closer spacing than 1/over the spacing in time, i.e. beyond the 'Fourier limit').
I have a question. How can I set null value into 0 on an image. Is there any way to do this in matlab. The image type is float-point, 32 bit, tif format. Null value (Nodata) of this image is -3.4028234663e+038. So the number is out of range of float-point. So I wanna replace those values with 0.
Generally speaking, you can find all the elements to replace by:
idx = (I == x); % # x is the "null" value
where I is your image and x is the desired value to replace (in your case, that is the "null" value). However, a more practical syntax would be using a certain threshold value instead of the exact value:
idx = (I > y); % # y is a value much lower than x
Now idx holds the logical indices of the elements you want to zero out. After you obtain idx, just do:
I(idx) = 0;
P.S
In practice, you can do achieve the same result without creating a temporary variable idx, like so:
I(I > y) = 0;