## New fan and internal cleaning of my Skull canyon NUC.

July 7, 2020 electronics No comments , , , ,

My “nuc1” has been inoperable for months, with a dead fan.  The replacement was delayed by the panic-demic significantly, but finally arrived today.  Here’s the NUC all opened up, with my replacement fan ready to be installed:

I had some trouble taking it out, and it turns out that it’s taped down, as well as screwed, so it just took some brute force.  However, check out the dust on the vents:

I’m wondering if the original fan was actually okay, and this beastie just needed a cleaning.  There wasn’t much surface area that would allow any air flow (just that tiny little corner), and I suspect that even that tiny little corner that wasn’t blocked was obscured before I pried up the old fan.

After cleaning the vents, and installing the new fan (I’d purchased it, so thought I may as well install it, even if the blocked ducts were the problem.), I can now run a parallel build without a constant barrage of temperature events.  I do get some:

but things return to normal and the lm_sensor package (sensors program) reports core temperatures within range, despite the parallel make:

This beastie runs hot, but I already knew that.  I see the temperatures spike during make, and get near the high threshold, but not all the way there.

I’m monitoring with both dmesg -w and sensors:

#!/bin/bash

# https://unix.stackexchange.com/questions/328906/find-fan-speed-and-cpu-temp-in-linux
sudo yum install lm_sensors

while [ 0 ] ; do clear ; sensors ; sleep 5 ; done


## Final touches for the kitchen renovation are now done.

June 22, 2020 Home renos 1 comment ,

Today included a second coat of paint, cleanup, and little bits of detailing.  The kitchen is now fully operational, and looking pretty sharp:

I also got the 2nd coat in the front foyer done today — we were saving that painting for last since we didn’t want traffic in and out of the house messing it up, and it’s looking good too (especially having removed the “popcorn” stucco from the ceiling.)

For anybody who had seen the old kitchen, observe that there is no longer a microwave embedded in the staircase for the basement (replaced with a more sensible microwave/range-hood combination.)

The bulkheads that on the fridge side of the kitchen are also now gone, and we were able to put in awesome floor to ceiling cabinets.  This will provide the new owners with lots of space!

## Antenna theory notes available on amazon

I’ve received my copy of my bound Antenna Theory notes today:

I wanted a copy for myself, but don’t expect that anybody else would buy this particular notes compilation.  The course was taught from slides, and it was almost impossible to take good notes, so these aren’t much good without also having the (excellent) course text (Balanis.)

The two possible reasons to buy or download this notes compilation would be:

• to peruse the solved problems, or
• for the geometric algebra and tensor formalism exploration that followed from wondering how to deal with the magnetic sources that are used in this subject.

I wouldn’t care if resellers undercut my list price, and then got a preferential listing from amazon.  The fact that this reseller doesn’t play this game with the color version of the book, which has a much higher printing cost (I haven’t changed my price for that, and am still selling it for $40 USD), suggests to me that I’d set the price too low for the black and white version. If you are interested in a copy of the book, but don’t like the new higher price, please note that the (color) PDF version is still available for free. I may drop the price back to the original$12 later, but for now I’m going to charge $14.50, and am curious to see how the pricing game plays out. Note that a temporary side effect of me having changed the price is that SuperBookDeals appears to have dropped their price of one of their listings below$12 (my original price) to clear out their stock. Amazon also appears to be offering a couple copies at the old $12 price, which now lists as a sale price. ## Unexpected COBOL implicit operator distribution! Another day, another surprise from COBOL. I was debugging a failure in a set of COBOL programs, and it seemed that the place things started going wrong was a specific IF check, which basically looked like: The original code was triple incomprehensible, as it: • Was in German. • Was in COBOL. • Was generated by DELTA and was completely disgusting spaghetti code. A map of the basic blocks would have looked like it was colored by a three year old vigorously scribbling with a crayon. It turns out that there was a whole pile of error handling code that happened after the IF check, and I correctly guessed that there was something wrong with how our compiler handled the IF statement. What I didn’t guess was what the actual operator precedence in this IF check was. Initially, my C programmer trained mind looked at that IF condition, and said “what the hell is that!?” I then guessed, incorrectly, that it meant: if ( X != SPACES and X = ZERO) where X is the array slice expression. That interpretation did not explain the runtime failure, so I was hoping that I was both wrong about what it meant, but right that there was a compiler bug. It turns out that in COBOL the implicit operator for the second part of the IF statement is ‘NOT =’. i.e. the NOT= distributes over the AND, so this IF actually meant: if ( X != SPACES and X != ZERO) In the original program, that IF condition actually makes sense. After some reflection, I see there is some sense to this distribution, but it certainly wasn’t intuitive after programming C and C++ for 27 years. I’d argue that the root cause of the confusion is COBOL itself. A real programming language would use a temporary variable for the really long array slice expression, which would obliterate the need for counter-intuitive operator distribution requirements. Imagine something like:  VAR X = PAYLOAD-DATA(PAYLOAD-START(TALLY): PAYLOAD-END(TALLY)) IF (X NOT = SPACES) AND (X NOT = LOW-VALUE) NEXT SENTENCE ELSE GO TO CHECK-IT-DONE.  (Incidentally LOW-VALUE means binary-zero, not a ‘0’ character that has a 0xF0 value in EBCDIC). COBOL is made especially incomprehensible since you can’t declare an in-line temporary in COBOL. If you want one, you have to go thousands of lines up in the code to the WORKING-STORAGE section, and put a variable in there somewhere. Such a variable is global to the whole program, and you have to search to determine it’s usage scope. You probably also need a really long name for it because of namespace collision with all the other global variables. Basically, you are better off not using any helper variables, unless you want to pay an explicit cost in overall code complexity. In my test program that illustrated the compiler bug, I made other COBOL errors. I blame the fact that I was using gross GOTO ridden code like the original. Here was my program: Because I misinterpreted the NOT= distribution, I thought this should produce: 000000001: !(not space and low-value.) 000000002: !(not space and low-value.) 000000003: !(not space and low-value.) 000000003: not space and low-value.  Once the subtle compiler bug was fixed, the actual SYSOUT from the program was: 000000001: not space and low-value. 000000001: !(not space and low-value.) 000000002: !(not space and low-value.) 000000003: !(not space and low-value.)  See how both the TRUE and FALSE basic blocks executed in my code. That didn’t occur in the original code, because it used an additional dummy EXIT paragraph to end the PERFORM range, and had a GOTO out of the first paragraph. There is more modern COBOL syntax that can avoid this GOTO hell, but I hadn’t used it, as I kept the reproducer somewhat like the original code. ## My collection of Peeter Joot physics paperbacks I ordered a copy of my old PHY456 Quantum Mechanics II notes for myself, and it arrived today! Here it is with it’s buddies (Grad QM and QFT): With the shipping cost from the US to Canada (because I’m now paying for amazon prime anyways) it’s actually cheaper for me to get a regular copy than to order an author proof, so this time I have no “not for resale” banding. This little stack of Quantum notes weighs in at about 1050 pages, and makes a rather impressive pile. There’s a lot of info there, for the bargain price of either free or about$30 USD, depending on whether you want a PDF or print copy of this set.  Of course, most people want neither, and get all their quantum mechanics through osmosis from the engineering of the microchips and electronics in their phones and computers.

I have to admit that it’s a fun ego boost to see your name in print.  In order to maximize the ego boost, you can use my strategy and do large scale vanity press, making a multiple volume set for yourself.  Here’s my whole collection, which includes the bulk of my course notes, plus my little book:

Based on the height of the stack, I’d guess this is about 3000 pages total, the product of about 10 years of study and work.

Making these all available for free to anybody in PDF form surely cripples my potential physical copy sales volume, but that doesn’t matter too much since I’ve set the price so low that I only get a token payment for each copy anyways.  Based on linear extrapolation of my sales so far, I’ll recoup my tuition costs (not counting the opportunity cost of working part time while I took the courses) after another 65 years of royalties.

## Does this COBOL level-88 IF check make any sense?

May 21, 2020 COBOL 2 comments ,

I find COBOL level-88 declarations a bit confusing, which isn’t made any easier by usage that is probably wrong. Here’s an example from code that I was trying to step through in the debugger (anonymized):

       WORKING-STORAGE SECTION.
01  data.
10  function-type         PIC  X(01).
88  option-a          VALUE '1'.
88  option-b          VALUE '2'.
88  option-c          VALUE '3'.
88  option-d          VALUE '4'.


With the use like so:

           IF option-a AND option-b AND option-c
NEXT SENTENCE ELSE GO TO meaningless-label-2.


It’s my understanding that this is essentially equivalent to:

           IF function-type = '1' AND function-type = '2' AND
function-type = '3'
NEXT SENTENCE ELSE GO TO meaningless-label-2.


Do I misunderstand the level-88 variables should be used, or is this just a plain old impossible-to-be-true if check? Putting this into a little sample program, confirms that we hit the ELSE:

       IDENTIFICATION DIVISION.
PROGRAM-ID.                 TESTPROG.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  data.
10  function-type         PIC  X(01).
88  option-a          VALUE '1'.
88  option-b          VALUE '2'.
88  option-c          VALUE '3'.
88  option-d          VALUE '4'.
PROCEDURE DIVISION.
move '1' to function-type

perform meaningless-label-1 thru meaningless-label-6

goback
.

meaningless-label-1.

*    IF function-type = '1' AND function-type = '2' AND
*       function-type = '3'
IF option-a AND option-b AND option-c
NEXT SENTENCE ELSE GO TO meaningless-label-2.

display 'IF was true.'

goto meaningless-label-6
.

meaningless-label-2.

display 'IF was not true.'
.

meaningless-label-6.
EXIT
.


I get SYSOUT of:

IF was not true.


as I expected. If these were level-88 variables each “belonging” to a different variable, such as:

       IDENTIFICATION DIVISION.
PROGRAM-ID.                 TESTPROG.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  data.
10  blah                 PIC  X(01).
88  blah-option-a                 VALUE '1'.
88  blah-option-b                 VALUE '2'.
10  foo                  PIC  X(01).
88  foo-option-a                  VALUE '1'.
88  foo-option-b                  VALUE '2'.
88  foo-option-c                  VALUE '3'.
10  bar                  PIC  X(01).
88  bar-option-c                  VALUE '3'.
88  bar-option-d                  VALUE '4'.

PROCEDURE DIVISION.
move '1' to blah
move '2' to foo
move '3' to bar

perform meaningless-label-1 thru meaningless-label-6

goback
.

meaningless-label-1.

IF blah-option-a AND foo-option-b AND bar-option-c
NEXT SENTENCE ELSE GO TO meaningless-label-2.

display 'IF was true.'

goto meaningless-label-6
.

meaningless-label-2.

display 'IF was not true.'
.

meaningless-label-6.
EXIT
.


This has the ‘IF was true’ SYSOUT. Perhaps the original coder meant to use OR instead of AND?

## COBOL spaghetti code: EXIT does nothing!

I was staring down COBOL code of the following form:

       LOOP-COUNTER-INCREMENT.
ADD 1 TO J.
LOOP-PREDICATE-CHECK.
IF J GREATER 10 GO TO MYSTERIOUS-LABEL-1.

IF ARRAY-1 (J)      NOT = ZERO
NEXT SENTENCE ELSE GO TO MYSTERIOUS-LABEL-1.

IF ARRAY-2 (J) = MYSTERIOUS-MAGIC-NUMBER-CONSTANT
NEXT SENTENCE ELSE GO TO COUNTER-INCREMENT-SPAGGETTIFI.

*     ...MORE STUFF...

GO TO MYSTERIOUS-LABEL-3.

COUNTER-INCREMENT-SPAGGETTIFI.
GO TO LOOP-COUNTER-INCREMENT.

MYSTERIOUS-LABEL-1.
EXIT.
MYSTERIOUS-LABEL-2.
EXIT.
MYSTERIOUS-LABEL-3.
EXIT.


I had to get some guru help understanding what this was about (thanks Roger!). I didn’t understand why somebody would code a GOTO LABEL, when the the code at that LABEL just did an EXIT. If my intuition could be trusted, I would have assumed that this code was equivalent to the much simpler:

       LOOP-COUNTER-INCREMENT.
ADD 1 TO J.
LOOP-PREDICATE-CHECK.
IF J GREATER 10 EXIT.

IF ARRAY-1 (J)      NOT = ZERO
NEXT SENTENCE ELSE EXIT.

IF ARRAY-2 (J) = MYSTERIOUS-MAGIC-NUMBER-CONSTANT
NEXT SENTENCE ELSE GO TO LOOP-COUNTER-INCREMENT.

*     ...MORE STUFF...

EXIT.


It turns out that intuition is not much use when looking at COBOL code. In this case, that intuition failure is because EXIT doesn’t actually do anything. It is not like a return, which is what I assumed, but is just something that you can put in a paragraph at the end of the section so that the code can exit the section (or at the end of a sequence of paragraphs invoked by PERFORM THRU, so that the code can return to the caller.)  The EXIT in such a paragraph is just a comment, and you could use an empty paragraph to do the same thing.

In my transformation of the code the EXIT would do nothing, and execution would just fall through to the next sentence!

Some of the transformations I made are valid. In particular, the spaghettification-indirection used to increment the loop counter, by using a goto to goto the target location instead of straight there, has no reason to exist.

The code in question was an edited version of a program that was generated by a 4GL language (DELTA), so some of the apparent stupidity can be blamed on the code generator. I also assume DELTA can also be blamed for the multiple EXIT paragraphs, when it would seem more natural to just have one per section.

This code also uses EXIT after other paragraph labels too. The first paragraph in the following serving of horror has such an example:

            PERFORM TRANSFER-CHECK THRU TRANSFER-CHECK-EXIT.

[snip]

TRANSFER-CHECK.
EXIT.
MEANINGLESS-LABEL-1.
IF [A COMPOUND PREDICATE CHECK]
NEXT SENTENCE ELSE GO TO MEANINGLESS-LABEL-2.
[SNIP]
PERFORM [MORE STUFF]
GO TO MEANINGLESS-LABEL-100.
MEANINGLESS-LABEL-2.
[STUFF]
GO TO MEANINGLESS-LABEL-4.
MEANINGLESS-LABEL-3.
[increment loop counter, and fall through]
MEANINGLESS-LABEL-4.
[loop body]
...
MEANINGLESS-LABEL-50.
GO TO MEANINGLESS-LABEL-3.
[SNIP]
...
MEANINGLESS-LABEL-99.
EXIT.
MEANINGLESS-LABEL-100.
EXIT.
TRANSFER-CHECK-EXIT.
EXIT.


Nothing ever branches to MEANINGLESS-LABEL-1 directly, so why even have that there? Using my new found knowledge that EXIT doesn’t do anything, I’m pretty sure that you could just write:

            PERFORM TRANSFER-CHECK THRU TRANSFER-CHECK-EXIT.

[snip]

TRANSFER-CHECK.

IF [A COMPOUND PREDICATE CHECK]


Is there some subtle reason that this first no-op paragraph was added? My guess is that the programmer was either being paid per line of code, or the code generator is to blame.

I’m not certain about the flow-control in the TRUE evaluation above. My intuition about the THRU use above is that if we have a GOTO that bypasses one of the paragraphs, then all the preceding paragraphs are counted as taken (i.e. if you get to the final paragraph in the THRU evaluation, no matter how you get there, then you are done.) I’ll have to do an experiment to determine if that’s actually the case.