Continuum mechanics notes now in book format at amazon.com

September 26, 2019 math and physics play , , , , , ,

My notes from the 2012 UofT session of phy454, Continuum mechanics (aka fluid mechanics), are now available in book form on amazon.com for $10 (black and white, softcover, 6×9″ format, 358 pages), as well as in PDF and latex formats as before.

I took that course as a non-degree student.  It was taught by Prof. Kausik S. Das, and had the official course description:

The theory of continuous matter, including solid and fluid mechanics. Topics include the continuum approximation, dimensional analysis, stress, strain, the Euler and Navier-Stokes equations, vorticity, waves, instabilities, convection and turbulence.

It was really only about fluid dynamics. Anything related to solids was really just to introduce the stress and strain tensors as lead up to expressing the Navier-Stokes equation. There was nothing in this course about beam deformation, Euler stability, or similar topics that one might have expected from the course description.

If you download the free PDF, compile the latex version, or buy a paper copy and feel undercharged, feel free to send some bitcoin my way.

Ugg, COBOL is so horrible.

September 23, 2019 Mainframe , , ,

If you don’t know COBOL (and I clearly don’t know it well enough), you probably won’t spot that there’s a syntax error here:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BLAH.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       LINKAGE SECTION.

       PROCEDURE DIVISION.

           DISPLAY 'BLAH.' UPON CONSOLE.

           STOP-RUN.

The C equivalent to this program is:

#include <stdio.h>
int main(){
  printf("BLAH.\n");
}

but it is meant to have an exit(0), so we want:

#include <stdio.h>
int main(){
  printf("BLAH.\n");
  return 0;
}

Translating that back into COBOL, we need the STOP-RUN statement to say STOP RUN (no dash).  With the -, this gets interpreted as a paragraph label (i.e. STOP-RUN delimits a new function) with no statements in it. What I did was something akin to:

#include <stdio.h>
void STOPRUN(){
}
int main(){
  printf("BLAH.\n");
  STOPRUN();
}

The final program doesn’t have the required ‘return 0’ or ‘exit(0)’ and blows up with a “No stop run nor go back” error condition.  Logically, what I really wanted was:

 

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BLAH.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       LINKAGE SECTION.

       PROCEDURE DIVISION.

           DISPLAY 'BLAH.' UPON CONSOLE

           STOP RUN

           .

 

This time I’ve left off the period that I had after CONSOLE (which was superfluous and should really only be used at the end of the paragraph (end of “function”)), and also fixes the STOP-RUN -> STOP RUN typo.

This is not the first time I’ve gotten mixed up on when to use DASHES or not.  For example, even above, I’d not expect a programmer to know or remember that you need to know to use dashes for WORKING-STORAGE and PROGRAM-ID but not for PROCEDURE DIVISION, nor some of the other space delimited fields.

My eyes are burning, and I left my COBOL programmer safety gear at home.

An example of Linux/glibc symbol versioning.

September 20, 2019 C/C++ development and debugging. , , , , , , ,

Here’s a little introduction to Linux/glibc symbol versioning.  The sources, linker version scripts, and makefile from this post can be found here in github.

The definitive reference for this topic is Ulrich Drepper’s dsohowto document.

Linux symbol versioning is a very logical way to construct a definitive API for your product.  If you are careful, you can have a single version of your shared library that is binary compatible with all previous versions of code that have linked it, and additionally hide all symbols that you don’t want your API consumer to be able to use (as if all non-exported symbols have a “static” like scope within the library itself).

That visibility hiding can be done in other ways (such as using static, or special compiler options), but utilizing a symbol version linker script to do so also has all the additional binary compatibility related benefits.

Suppose that we have a “v1.1” API with the following implementation:

#include <stdio.h>

void internal_function_is_not_visible()
{
   printf( "You can't call me directly.\n" );
}

void foo( int x )
{
   internal_function_is_not_visible();

   printf( "foo@@V1: %d\n", x );
}

and we build this into a shared library like so:

$ make libfoo.1.so
rm -f libfoo.1.so
cc foo.c -g -Wl,--version-script=symver.map -fpic -o libfoo.1.so -Wl,-soname,libfoo.so -shared
rm -f libfoo.so
ln -s libfoo.1.so libfoo.so

Everything here is standard for building a shared library except for the –version-script option that is passed into the linker with -Wl,. That version script file has the following contents:

$ cat symver.map
MYSTUFF_1.1 {
	  global:
foo;
	  local: *;
	};

This defines a “V1.1” API where all the symbols that are exported with a symbol version @@MYSTUFF_1.1. Note that internal_function_is_not_visible is not in that list. It’s covered in the local: catch-all portion of the symbol version file. Code that calls foo does not look out of the ordinary:

void foo(int);

int main()
{
   foo(1);

   return 0;
}

Compiling and linking that code is also business as usual:

$ make caller1
cc caller.c -g -Wl,-rpath,`pwd` -o caller1 -lfoo -L.

However, look at the foo symbol reference that we have for this program:

$ nm caller1 | grep foo
                 U foo@@MYSTUFF_1.1

If we run this, we get:

$ ./caller1
You can't call me directly.
foo@@V1: 1

If you add in a call to internal_function_is_not_visible() you’ll see that compilation fails:

void foo(int);
void internal_function_is_not_visible();

int main()
{
   foo(1);
   internal_function_is_not_visible();

   return 0;
}

$ make caller1
cc caller.c -g -Wl,-rpath,`pwd` -o caller1 -lfoo -L.
/run/user/1002/ccqEPYcu.o: In function `main':
/home/pjoot/symbolversioning/caller.c:7: undefined reference to `internal_function_is_not_visible'
collect2: error: ld returned 1 exit status
make: *** [caller1] Error 1

This is because internal_function_is_not_visible is not a visible symbol. Cool. We now have versioned symbols and symbol hiding. Suppose that we now want to introduce a new binary incompatible change too our foo API, but want all existing binaries to still work unchanged. We can do so by introducing a symbol alias, and implementations for both the new and the OLD API.

#include <stdio.h>

void internal_function_is_not_visible()
{
   printf( "You can't call me directly.\n" );
}

void foo2( int x, int y )
{
   if ( y < 2 )
   {
      internal_function_is_not_visible();
   }
   printf( "foo@@V2: %d %d\n", x, y );
}

void foo1( int x )
{
   internal_function_is_not_visible();
   printf( "foo@@V1: %d\n", x );
}

This is all standard C up to this point, but we now add in a little bit of platform specific assembler directives (using gcc specific compiler sneaks) :

#define V_1_2 "MYSTUFF_1.2"
#define V_1_1 "MYSTUFF_1.1"

#define SYMVER( s ) \
    __asm__(".symver " s )

SYMVER( "foo1,foo@" V_1_1 );
SYMVER( "foo2,foo@@" V_1_2 );

We’ve added a symbol versioning alias for foo@@MYSTUFF_1.2 and foo@MYSTUFF_1.1. The @@ one means that it applies to new code, whereas the @MYSTUFF_1.1 is a load only function, and no new code can use that symbol. In the symbol version script we now introduce a new version stanza:

$ cat symver.2.map
MYSTUFF_1.2 {
	  global:
foo;
};
MYSTUFF_1.1 {
	  global:
foo;
	  local: *;
};

$ make libfoo.2.so
rm -f libfoo.2.so
cc foo.2.c -g -Wl,--version-script=symver.2.map -fpic -o libfoo.2.so -Wl,-soname,libfoo.so -shared
rm -f libfoo.so
ln -s libfoo.2.so libfoo.so

If we call the new V1.2 API program, like so:

void foo(int, int);
int main()
{
   foo(1, 2);
   return 0;
}

our output is now:

$ ./caller2
foo@@V2: 1 2

Our “binary incompatible changes” are two fold. We don’t call internal_function_is_not_visible if our new parameter is >= 2, and we print a different message.

If you look at the symbols that are referenced by the new binary, you’ll see that it now explicitly has a v1.2 dependency:

$ nm caller2 | grep foo
                 U foo@@MYSTUFF_1.2

Book sales stats: slow and steady

September 2, 2019 Incoherent ramblings

I don’t have full stats for all my kindle-direct sales, but am surprised how steady the sales for the GA book have been

Jan 1- March 31 2019 April 1 – June 30, 2019 June 4 – Sept 1, 2019

Geometric Algebra for Electrical Engineers

24 24 26

Statistical Mechanics

3 2

Relativistic Electrodynamics

2

Classical Optics

4

Quantum Field Theory

2 2

Condensed Matter

1

Graduate Quantum Mechanics

1

Some of the earlier sales were to family members who wanted copies, but the rest are legitimate.

An easy fix for a loose electrical outlet

September 1, 2019 Home renos

We’ve had a dangerously seeming loose wall outlet since we moved in, and I’ve been meaning to deal with it forever. This was one of those little projects that I procrastinated forever, since it was one that I figured would be messy, but also one that I knew I wouldn’t know what I had to do until I started.

Here’s the outlet with the cover off

one side sticks out about 3/8″ of an inch, and the whole thing is loose, with about a 1/4″ of play in many spots.

As it turned out, the stud that the outlet was attached to was rotated about 35 degrees, which was the root of the problem. You can see that in this picture, if you look closely, as I have the blade of the drywall saw at the bottom of the hole perpendicular to the wall surface, and touching the back edge of the stud:

I ended up cutting a giant hole, big enough that I could try to run a new parallel stud. However, reaching in to my giant hole, I found that there was enough slack that I could reroute the wires to the unused box beside it. That unused box had an unused telephone wire it, and has always had a blank cover plate on it:

Despite being a box for telephone wire, it wasn’t a low voltage box, but was a standard electrical grade box, so I was able to fix the loose outlet by just recycling the unused box for the once loose outlet:

 

Now I just have a hole to patch:

I’ve put in strapping to anchor the drywall patch to, but it seems that I’ve thrown out all my drywall scraps, so the next steps will have to wait a bit.