http://alecjacobson.com/art/digital/
http://alecjacobson.com/art/
Archive for November, 2011
eddie o’dowd
Saturday, November 26th, 2011Self-compiling .cpp file
Thursday, November 17th, 2011I often put compilation notes in the comments at the top of small .cpp programs. These are just reminders to me of the flags I need to set in g++ to compile the program. For bigger programs I use Xcode or Makefiles, but often if I’m just testing a small idea I don’t want that overhead.
I had a funny idea today that my .cpp file could act as both a bash script and as C++ code. Then I could execute the .cpp file (as a bash script) which would set up the compiler and then compile itself. Here’s a proof of concept, save this in main.cpp
#!/bin/bash
//usr/bin/tail -n +2 $0 | g++ -o main -x c++ - && exit
#include <cstdio>
int main(int argc,char * argv[])
{
printf("Hello, world\n");
return 0;
}
Make it executable with
chmod +x main.cpp
To compile just execute the cpp file:
./main.cpp
This creates the real binary of the program which you can execute with:
./main
Update:
If you don’t like the hassle of making the binary you can just run the binary right after you compile it, then delete it immediately. Do this by changing the second line to:
#!/bin/bash
//usr/bin/tail -n +2 $0 | g++ -o main -x c++ - && ./main && rm main && exit
#include <cstdio>
int main(int argc,char * argv[])
{
printf("Hello, world\n");
return 0;
}
Update:
With an additional hack you can have a full fledged bash script at the top of your .cpp file:
#!/bin/bash
/*/../bin/ls > /dev/null
# BEGIN BASH SCRIPT
printf "//" | cat - $0 | g++ -o .main -x c++ - && ./.main $@
rm -f .main
# END BASH SCRIPT
exit
*/
#include <cstdio>
int main(int argc,char * argv[])
{
printf("Hello, world\n");
return 0;
}
Update: Here’s another one I found especially useful. This allows me to pipe the output to colormake to get colorized terminal compiler output.
#!/bin/bash
/*/../bin/ls > /dev/null
# BEGIN BASH SCRIPT
export PS4=""
set -o xtrace
printf "//" | cat - $0 | g++ -o .main -x c++ - && ./.main $@
rm -f .main
# END BASH SCRIPT
exit
*/
#include <cstdio>
int main(int argc,char * argv[])
{
printf("Hello, world\n");
return 0;
}
Then I pipe the output to colormake using:
./main.cpp 2>&1 | colormake.pl
max schmeling overcome
Thursday, November 17th, 20112D rotation matrix plus another 2D rotation matrix is a similarity matrix (scaled 2D rotation)
Wednesday, November 16th, 2011Consider we have two rotation matrices:
R1 = / cos(θ1) -sin(θ1) \
\ sin(θ1) cos(θ1) /
R2 = / cos(θ2) -sin(θ2) \
\ sin(θ2) cos(θ2) /
Then we can show that:
R1 + R2 = s * R3
where s is a scalar and R3 is another 2D rotation.
First we just add the components to get:
R1 + R2 = / cos(θ1)+cos(θ2) -(sin(θ1)+sin(θ2)) \
\ sin(θ1)+sin(θ2) cos(θ1)+cos(θ2) /
Notice we already have the right pattern:
R1 + R2 = / A -B \
\ B A /
we just need to show that we can pull out a common scaling term and angle from A and B.
We can use trigonometric identities to turn the sums of cosines and the sums of sines into products, namely:
cos(θ1)+cos(θ2) = 2*cos((θ1+θ2)/2)*cos((θ1-θ2)/2)
sin(θ1)+sin(θ2) = 2*sin((θ1+θ2)/2)*cos((θ1-θ2)/2)
Now we declare that:
s = 2*cos((θ1-θ2)/2)
θ3 = (θ1+θ2)/2
Then it follows that:
R1 + R2
=
/ s*cos((θ1+θ2)/2) -s*sin((θ1+θ2)/2) \
\ s*sin((θ1+θ2)/2) s*cos((θ1+θ2)/2) /
=
s * / cos(θ3) -sin(θ3) \
\ sin(θ3) cos(θ3) /
=
s * R3
More useful ease curves
Wednesday, November 16th, 2011The simplest ease function and the easiest to remember is a cubic:
3*t.^2-2*t.^3
For even better continuity at the corners we could use a fifth order:
10*t.^3 - 15*t.^4 + 6*t.^5
Of course we could always just compose smooth, ease functions to get higher order ones. For example composing the cubic gives:
3*(3*t.^2-2*t.^3).^2-2*(3*t.^2-2*t.^3).^3
So far the ease curves have been symmetric on either side of t=0.5, a useful asymmetric curve is half of a uniform biplane basis function rescaled to fit in the unit square. This one is a piecewise cubic:
2*t.^3 .* (t<0.5) + ...
(1-6*t+12*t.^2-6*t.^3) .* (t>=0.5)
Notice how I use multiplication against a logical to construct piecewise functions in matlab.
To see them in action use:
t = linspace(0,1,100);
plot( ...
t,3*t.^2-2*t.^3, ...
t,10*t.^3 - 15*t.^4 + 6*t.^5, ...
t,3*(3*t.^2-2*t.^3).^2-2*(3*t.^2-2*t.^3).^3, ...
t,2*t.^3 .* (t<0.5) + ...
(1-6*t+12*t.^2-6*t.^3) .* (t>=0.5), ...
'LineWidth',2 ...
);
The nice legend is created with:
nl = @(s) strrep(s,'\n',char(10));
legend({ ...
'3t^2-2t^3', ...
'10t^3-15t^4+6t^5', ...
nl('3u^2-2u^3\nu = 3t^2-2t^3'), ...
nl('2t^3 t<0.5\n1-6t+12d^2-6t^3 t>=0')}, ...
'FontName','FixedWidth', ...
'Location','NorthWest', ...
'FontSize',11);
New lines in matlab, figure legends and elsewhere
Wednesday, November 16th, 2011I tried naively to use \n in a matlab string hoping that it would come out as the newline character:
a = 'first\nsecond'
But you just get literally the 2 characters, \ and n in your string.
a =
first\nsecond
You code filter your string through sprintf:
b = sprintf('first\nsecond')
which gives you the newline:
b =
first
second
But this would cause problems if your string happened to contain any of the other sprintf symbols, like %, resulting in missing characters or errors:
sprintf('percentage\n90%')
Puts in the newline but removes the % sign:
ans =
percentage
90
Instead, it’s best to use the character code for the new line directly:
c = ['first' char(10) 'second'];
Concatenating strings in matlab is clunky but the newline shows up correctly without any side effects:
c =
first
second
You could easily make a simple replacement function that finds any \n sequences and replaces them with char(10)s with the following:
nl = @(s) strrep(s,'\n',char(10));
Then use your new function nl on your original string with \n to get the newline without worrying about concatenating:
d = nl('first\nsecond');
producing
d =
first
second
Re-sort using second output of sort in Matlab
Tuesday, November 15th, 2011Matlab’s sort function gives you a secondary output which can be used to resort your matrix. If you’re sorting each row of an m by n matrix V then:
[SV,I] = sort(V,2);
gives you the m by n indexing matrix I which for each rows tell the ordering of V needed to produce the corresponding row in SV
To reproduce the sort of the entire matrix again you can use
reSV = V(sub2ind(size(V),repmat(1:size(V,1),size(V,2),1)',I));
united states of puerto rico
Monday, November 14th, 2011List of United States, list of European Union states ordered by descending population
Monday, November 14th, 2011|
California Texas New York Florida Illinois Pennsylvania Ohio Michigan Georgia North Carolina New Jersey Virginia Washington Massachusetts Indiana Arizona Tennessee Missouri Maryland Wisconsin Minnesota Colorado Alabama South Carolina Louisiana Kentucky Oregon Oklahoma Puerto Rico Connecticut Iowa Mississippi Arkansas Kansas Utah Nevada New Mexico West Virginia Nebraska Idaho Hawaii Maine New Hampshire Rhode Island Montana Delaware South Dakota Alaska North Dakota Vermont Washington, DC Wyoming |
Germany France United Kingdom Italy Spain Poland Romania Netherlands Portugal Greece Belgium Czech Republic Hungary Sweden Austria Bulgaria Denmark Slovakia Finland Ireland Lithuania Latvia Slovenia Estonia Cyprus Luxembourg Malta |




