http://alecjacobson.com/art/digital/

http://alecjacobson.com/art/

## Archive for November, 2011

### eddie o’dowd

Saturday, November 26th, 2011### Self-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
```

**Update:** Yet another one. This time works with the debugger.

TEMP=”$0.cpp” printf “//” | cat – $0 >$TEMP

```
#!/bin/bash
/*/../bin/ls > /dev/null
# BEGIN BASH SCRIPT
source ~/.profile
export PS4=""
set -o xtrace
printf "//" | cat - $0 |
g++ -g -O0 -std=c++11 -o .main $TEMP && \
/Applications/Xcode.app/Contents/Developer/usr/bin/lldb -b -o r ./main -- "$@"
rm -f .main
# END BASH SCRIPT
exit
*/
#include <cstdio>
int main(int argc,char * argv[])
{
printf("Hello, world\n");
return 0;
}
```

**Update:** I edited the above to include `source ~/.profile`

. Seems with El Capitan Mac OS 10.11 the `DYLD_FALLBACK_LIBRARY_PATH`

setting is not persistent when call a script from `vim`

.

### max schmeling overcome

Thursday, November 17th, 2011### 2D rotation matrix plus another 2D rotation matrix is a similarity matrix (scaled 2D rotation)

Wednesday, November 16th, 2011Consider we have two rotation matrices:

```
R
```_{1} = / cos(θ_{1}) -sin(θ_{1}) \
\ sin(θ_{1}) cos(θ_{1}) /
R_{2} = / cos(θ_{2}) -sin(θ_{2}) \
\ sin(θ_{2}) cos(θ_{2}) /

Then we can show that:

```
R
```_{1} + R_{2} = s * R_{3}

where s is a scalar and R_{3} is another 2D rotation.

First we just add the components to get:

```
R
```_{1} + R_{2} = / cos(θ_{1})+cos(θ_{2}) -(sin(θ_{1})+sin(θ_{2})) \
\ sin(θ_{1})+sin(θ_{2}) cos(θ_{1})+cos(θ_{2}) /

Notice we already have the right pattern:

```
R
```_{1} + R_{2} = / 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:

```
R
```_{1} + R_{2}
=
/ 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 * R_{3}

### 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, 2011### List 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 |