Granite Mon 2012

:: granitemon

By: John Clements

As I write this, it’s Monday, August 6th. Charlotte Clews is organizing this year, and it appears that there will be two events that include the swim; the Maine Mountain Challenge, and the Granite Mon. Yesterday was the first swim. Here’s the picture:

2012 Swimmers

2012 Swimmers

From left, the swimmers:

  • Charlotte Clews,
  • Jerome Lawther,
  • Justin Pollard,
  • John Clements,
  • Mary Clews,
  • first-time-swimmer Pat Starkey, and
  • Moira McMahon

The water was extremely warm: Global Warming will kill millions of people, but it made Sunday morning easier. I think it was at or above 70 degrees. High tide wasn’t until 2:00 PM, so we started quite late. We met at the KYC at 9:30, and I don’t think we started swimming until about 11:00. We all arrived at about the same time; I got in at an hour and 28 minutes, and I think we were all in before 1:38.

There may have been a ride to Cadillac and a hike up it, but I’ll have to wait until I hear more to write about that.

Random Code 9: Perl

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#
# Globals:
#

# Regex to match balanced [brackets]. See Friedl's
# "Mastering Regular Expressions", 2nd Ed., pp. 328-331.
my $g_nested_brackets;
$g_nested_brackets = qr{
	(?> 								# Atomic matching
	   [^\[\]]+							# Anything other than brackets
	 | 
	   \[
		 (??{ $g_nested_brackets })		# Recursive set of nested brackets
	   \]
	)*
}x;


# Table of hash values for escaped characters:
my %g_escape_table;
foreach my $char (split //, '\\`*_{}[]()>#+-.!') {
	$g_escape_table{$char} = md5_hex($char);
}


# Global hashes, used by various utility routines
my %g_urls;
my %g_titles;
my %g_html_blocks;

# Used to track when we're inside an ordered or unordered list
# (see _ProcessListItems() for details):
my $g_list_level = 0;


#### Blosxom plug-in interface ##########################################

# Set $g_blosxom_use_meta to 1 to use Blosxom's meta plug-in to determine
# which posts Markdown should process, using a "meta-markup: markdown"
# header. If it's set to 0 (the default), Markdown will process all
# entries.
my $g_blosxom_use_meta = 0;

sub start { 1; }
sub story {
	my($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;

	if ( (! $g_blosxom_use_meta) or
	     (defined($meta::markup) and ($meta::markup =~ /^\s*markdown\s*$/i))
	     ){
			$$body_ref  = Markdown($$body_ref);
     }
     1;
}

“Project 2 Testing”

:: Programming Languages

By: John Clements

{% gist 2411008 %}

{% gist 2411005 %}

{% gist 2411004 %}

{% gist 2411002 %}

{% gist 2410993 %}

{% gist 2410918 %}

{% gist 2410916 %}

{% gist 2410910 %}

{% gist 2410909 %}

{% gist 2410908 %}

{% gist 2410905 %}

{% gist 2410904 %}

{% gist 2410899 %}

{% gist 2410889 %}

{% gist 2410886 %}

{% gist 2410882 %}

{% gist 2410860 %}

{% gist 2410856 %}

random code 8: urrgggh

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php


namespace Symfony\Component\Form\Tests\Extension\Core\Type;

use Symfony\Component\Form\FormError;

class DateTimeTypeTest extends LocalizedTestCase
{
    public function testSubmit_dateTime()
    {
        $form = $this->factory->create('datetime', null, array(
            'data_timezone' => 'UTC',
            'user_timezone' => 'UTC',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
            'input' => 'datetime',
        ));

        $form->bind(array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
            ),
        ));

        $dateTime = new \DateTime('2010-06-02 03:04:00 UTC');

        $this->assertDateTimeEquals($dateTime, $form->getData());
    }

    public function testSubmit_string()
    {
        $form = $this->factory->create('datetime', null, array(
            'data_timezone' => 'UTC',
            'user_timezone' => 'UTC',
            'input' => 'string',
            'date_widget' => 'choice',
            'time_widget' => 'choice',
        ));

        $form->bind(array(
            'date' => array(
                'day' => '2',
                'month' => '6',
                'year' => '2010',
            ),
            'time' => array(
                'hour' => '3',
                'minute' => '4',
            ),
        ));

        $this->assertEquals('2010-06-02 03:04:00', $form->getData());
    }
...
}

Random Code 7: sh

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Check for updates on initial load...
if [ "$DISABLE_AUTO_UPDATE" != "true" ]
then
  /usr/bin/env ZSH=$ZSH zsh $ZSH/tools/check_for_upgrade.sh
fi

# Initializes Oh My Zsh

# add a function path
fpath=($ZSH/functions $ZSH/completions $fpath)

# Load all of the config files in ~/oh-my-zsh that end in .zsh
# TIP: Add files you don't want in git to .gitignore
for config_file ($ZSH/lib/*.zsh) source $config_file

# Set ZSH_CUSTOM to the path where your custom config files
# and plugins exists, or else we will use the default custom/
if [[ -z "$ZSH_CUSTOM" ]]; then
    ZSH_CUSTOM="$ZSH/custom"
fi


is_plugin() {
  local base_dir=$1
  local name=$2
  test -f $base_dir/plugins/$name/$name.plugin.zsh \
    || test -f $base_dir/plugins/$name/_$name
}
# Add all defined plugins to fpath. This must be done
# before running compinit.
for plugin ($plugins); do
  if is_plugin $ZSH_CUSTOM $plugin; then
    fpath=($ZSH_CUSTOM/plugins/$plugin $fpath)
  elif is_plugin $ZSH $plugin; then
    fpath=($ZSH/plugins/$plugin $fpath)
  fi
done

# Load and run compinit
autoload -U compinit
compinit -i


# Load all of the plugins that were defined in ~/.zshrc
for plugin ($plugins); do
  if [ -f $ZSH_CUSTOM/plugins/$plugin/$plugin.plugin.zsh ]; then
    source $ZSH_CUSTOM/plugins/$plugin/$plugin.plugin.zsh
  elif [ -f $ZSH/plugins/$plugin/$plugin.plugin.zsh ]; then
    source $ZSH/plugins/$plugin/$plugin.plugin.zsh
  fi
done

# Load all of your custom configurations from custom/
for config_file ($ZSH_CUSTOM/*.zsh) source $config_file

# Load the theme
if [ "$ZSH_THEME" = "random" ]
then
  themes=($ZSH/themes/*zsh-theme)
  N=${#themes[@]}
  ((N=(RANDOM%N)+1))
  RANDOM_THEME=${themes[$N]}
  source "$RANDOM_THEME"
  echo "[oh-my-zsh] Random theme '$RANDOM_THEME' loaded..."
else
  if [ ! "$ZSH_THEME" = ""  ]
  then
    if [ -f "$ZSH/custom/$ZSH_THEME.zsh-theme" ]
    then
      source "$ZSH/custom/$ZSH_THEME.zsh-theme"
    else
      source "$ZSH/themes/$ZSH_THEME.zsh-theme"
    fi
  fi
fi

random code 6: Python

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class SelectDateWidget(Widget):
    """
    A Widget that splits date input into three <select> boxes.

    This also serves as an example of a Widget that has more than one HTML
    element and hence implements value_from_datadict.
    """
    none_value = (0, '---')
    month_field = '%s_month'
    day_field = '%s_day'
    year_field = '%s_year'

    def __init__(self, attrs=None, years=None, required=True):
        # years is an optional list/tuple of years to use in the "year" select box.
        self.attrs = attrs or {}
        self.required = required
        if years:
            self.years = years
        else:
            this_year = datetime.date.today().year
            self.years = range(this_year, this_year+10)

    def render(self, name, value, attrs=None):
        try:
            year_val, month_val, day_val = value.year, value.month, value.day
        except AttributeError:
            year_val = month_val = day_val = None
            if isinstance(value, basestring):
                if settings.USE_L10N:
                    try:
                        input_format = get_format('DATE_INPUT_FORMATS')[0]
                        v = datetime.datetime.strptime(value, input_format)
                        year_val, month_val, day_val = v.year, v.month, v.day
                    except ValueError:
                        pass
                else:
                    match = RE_DATE.match(value)
                    if match:
                        year_val, month_val, day_val = [int(v) for v in match.groups()]
        choices = [(i, i) for i in self.years]
        year_html = self.create_select(name, self.year_field, value, year_val, choices)
        choices = MONTHS.items()
        month_html = self.create_select(name, self.month_field, value, month_val, choices)
        choices = [(i, i) for i in range(1, 32)]
        day_html = self.create_select(name, self.day_field, value, day_val,  choices)

        output = []
        for field in _parse_date_fmt():
            if field == 'year':
                output.append(year_html)
            elif field == 'month':
                output.append(month_html)
            elif field == 'day':
                output.append(day_html)
        return mark_safe(u'\n'.join(output))

Random Code 5: opoo

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  def link
    if f.linked_keg.directory? and f.linked_keg.realpath == f.prefix
      opoo "This keg was marked linked already, continuing anyway"
      # otherwise Keg.link will bail
      f.linked_keg.unlink
    end

    keg = Keg.new(f.prefix)
    keg.link
  rescue Exception => e
    onoe "The linking step did not complete successfully"
    puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
    puts "You can try again using `brew link #{f.name}'"
    keg.unlink

    ohai e, e.backtrace if ARGV.debug?
    @show_summary_heading = true
  end

  def fix_install_names
    Keg.new(f.prefix).fix_install_names
  rescue Exception => e
    onoe "Failed to fix install names"
    puts "The formula built, but you may encounter issues using it or linking other"
    puts "formula against it."
    ohai e, e.backtrace if ARGV.debug?
    @show_summary_heading = true
  end

  def clean
    require 'cleaner'
    Cleaner.new f
  rescue Exception => e
    opoo "The cleaning step did not complete successfully"
    puts "Still, the installation was successful, so we will link it into your prefix"
    ohai e, e.backtrace if ARGV.debug?
    @show_summary_heading = true
  end

  def pour
    fetched, downloader = f.fetch
    f.verify_download_integrity fetched, f.bottle_sha1, "SHA1"
    HOMEBREW_CELLAR.cd do
      downloader.stage
    end
  end

Random Code 4

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  , slide: function (type, next) {
      var $active = this.$element.find('.active')
        , $next = next || $active[type]()
        , isCycling = this.interval
        , direction = type == 'next' ? 'left' : 'right'
        , fallback  = type == 'next' ? 'first' : 'last'
        , that = this

      this.sliding = true

      isCycling && this.pause()

      $next = $next.length ? $next : this.$element.find('.item')[fallback]()

      if ($next.hasClass('active')) return

      if (!$.support.transition && this.$element.hasClass('slide')) {
        this.$element.trigger('slide')
        $active.removeClass('active')
        $next.addClass('active')
        this.sliding = false
        this.$element.trigger('slid')
      } else {
        $next.addClass(type)
        $next[0].offsetWidth // force reflow
        $active.addClass(direction)
        $next.addClass(direction)
        this.$element.trigger('slide')
        this.$element.one($.support.transition.end, function () {
          $next.removeClass([type, direction].join(' ')).addClass('active')
          $active.removeClass(['active', direction].join(' '))
          that.sliding = false
          setTimeout(function () { that.$element.trigger('slid') }, 0)
        })
      }

much nerdier than spock

::

By: John Clements

My family has taken to watching the Big Bang Theory, and while I am extraordinarily tired of the laugh track, I continue to watch.

Naturally, any show targeted at nerds is bound to draw the ire of nerds, who are famed for their desire to find flaws in the opinions and statements of others, especially those who consider themselves nerdy. Indeed, an all-consuming desire for intellectual one-upsmanship (cf. Stephen Potter’s excellent books on the topic) may perhaps be regarded as the sine qua non of nerdhood. This desire can also manifest itself in the needless selection of lengthier words at the expense of more concise ones, the tendency to cite obscure sources, and the general tendency to blather at length.

But I digress.

I would like to take issue on this occasion with the recurring incidence of the game “Rock, Paper, Scissors, Lizard, Spock.” It has a fine wikipedia page, and I won’t describe it here.

My issue is that this RPS variant—and indeed, all of the ones I’ve seen published—can concisely be expressed as simple games of modulo arithmetic. That is:

  • You pick a number from one to five.
  • I pick a number from one to five.
  • Take my number minus your number, modulo five.
  • If the result is one or two, I win.
  • If the result is three or four, you win.
  • If the result is zero, we tie.

Naturally, you can generalize this to any odd number.

It seems to me that this is at the same time simpler, more general, and more nerdy than the game played by those on the show, and I would hope that they would consider changing to my variant, which I call John Brinckerhoff Clements.

Yes, there’s a note on this in the Wikipedia page. Yes, I added it.

One final note: an even nerdier version of this game may be played, still with the fingers of one hand, by throwing any combination of one through four fingers, and interpreting this as a binary number from 0 through 15. I humbly suggest interpreting an extended finger as the digit 1, a non-extended finger as the digit 0, the index finger as the most significant, the little finger as the least significant, and “wrapping around” to regard all fingers extended as a zero.

In fact, this game allows direct comparison of several popular hand gestures. Specifically:

  • “rock” beats “American f*** you”:

rock hand > eff you hand

  • “peace” beats “rock”:

peace hand > rock hand

  • “Spock” beats the two prior:

spock hand > peace hand

  • and “Englishman Drinking Tea” beats “Spock”:

drinking tea hand > spock hand

This hand is not a game entry. If you see this shape, your opponent is not playing the game:

illegal hand

illegal hand

So the next time someone gives you the finger, just point directly at them, and you win.

random code 3: first look at FORTRAN

:: CodeCritic, Programming Languages

By: John Clements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  !================================================================================================================================
  !

  !>Initialises the interpolated point metrics for an interpolated point.
  SUBROUTINE FIELD_INTERPOLATED_POINT_METRICS_INITIALISE(INTERPOLATED_POINT,INTERPOLATED_POINT_METRICS,ERR,ERROR,*)

    !Argument variables
    TYPE(FIELD_INTERPOLATED_POINT_TYPE), POINTER :: INTERPOLATED_POINT !A pointer to the interpolated point to initliase the interpolated point metrics for
    TYPE(FIELD_INTERPOLATED_POINT_METRICS_TYPE), POINTER :: INTERPOLATED_POINT_METRICS !<On exit, a pointer to the interpolated point metrics that have been initialised
    INTEGER(INTG), INTENT(OUT) :: ERR !<The error code
    TYPE(VARYING_STRING), INTENT(OUT) :: ERROR !<The error string
    !Local Variables
    INTEGER(INTG) :: NUMBER_OF_XI_DIMENSIONS,NUMBER_OF_X_DIMENSIONS
    INTEGER(INTG) :: DUMMY_ERR
    TYPE(COORDINATE_SYSTEM_TYPE), POINTER :: COORDINATE_SYSTEM
    TYPE(VARYING_STRING) :: DUMMY_ERROR,LOCAL_ERROR

    CALL ENTERS("FIELD_INTERPOLATED_POINT_METRICS_INITIALISE",ERR,ERROR,*999)

    IF(ASSOCIATED(INTERPOLATED_POINT)) THEN
      IF(ASSOCIATED(INTERPOLATED_POINT_METRICS)) THEN
        CALL FLAG_ERROR("Interpolated point metrics is already associated.",ERR,ERROR,*998)
      ELSE
        NULLIFY(COORDINATE_SYSTEM)
        CALL FIELD_COORDINATE_SYSTEM_GET(INTERPOLATED_POINT%INTERPOLATION_PARAMETERS%FIELD,COORDINATE_SYSTEM,ERR,ERROR,*999)
        NUMBER_OF_X_DIMENSIONS=COORDINATE_SYSTEM%NUMBER_OF_DIMENSIONS
        NUMBER_OF_XI_DIMENSIONS=INTERPOLATED_POINT%INTERPOLATION_PARAMETERS%FIELD%DECOMPOSITION%MESH%NUMBER_OF_DIMENSIONS
        IF(NUMBER_OF_X_DIMENSIONS==SIZE(INTERPOLATED_POINT%VALUES,1)) THEN
          ALLOCATE(INTERPOLATED_POINT_METRICS,STAT=ERR)
          IF(ERR/=0) CALL FLAG_ERROR("Could not allocate interpolated point metrics.",ERR,ERROR,*999)
          ALLOCATE(INTERPOLATED_POINT_METRICS%GL(NUMBER_OF_XI_DIMENSIONS,NUMBER_OF_XI_DIMENSIONS),STAT=ERR)
          IF(ERR/=0) CALL FLAG_ERROR("Could not allocate interpolated point metrics convariant tensor.",ERR,ERROR,*999)
          ALLOCATE(INTERPOLATED_POINT_METRICS%GU(NUMBER_OF_XI_DIMENSIONS,NUMBER_OF_XI_DIMENSIONS),STAT=ERR)
          IF(ERR/=0) CALL FLAG_ERROR("Could not allocate interpolated point metrics contravariant tensor.",ERR,ERROR,*999)
          ALLOCATE(INTERPOLATED_POINT_METRICS%DX_DXI(NUMBER_OF_X_DIMENSIONS,NUMBER_OF_XI_DIMENSIONS),STAT=ERR)
          IF(ERR/=0) CALL FLAG_ERROR("Could not allocate interpolated point metrics dX_dXi.",ERR,ERROR,*999)
          ALLOCATE(INTERPOLATED_POINT_METRICS%DXI_DX(NUMBER_OF_XI_DIMENSIONS,NUMBER_OF_X_DIMENSIONS),STAT=ERR)
          IF(ERR/=0) CALL FLAG_ERROR("Could not allocate interpolated point metrics dXi_dX.",ERR,ERROR,*999)
          INTERPOLATED_POINT_METRICS%INTERPOLATED_POINT=>INTERPOLATED_POINT
          INTERPOLATED_POINT_METRICS%NUMBER_OF_X_DIMENSIONS=NUMBER_OF_X_DIMENSIONS
          INTERPOLATED_POINT_METRICS%NUMBER_OF_XI_DIMENSIONS=NUMBER_OF_XI_DIMENSIONS
          INTERPOLATED_POINT_METRICS%GL=0.0_DP
          INTERPOLATED_POINT_METRICS%GU=0.0_DP
          INTERPOLATED_POINT_METRICS%DX_DXI=0.0_DP
          INTERPOLATED_POINT_METRICS%DXI_DX=0.0_DP
          INTERPOLATED_POINT_METRICS%JACOBIAN=0.0_DP
          INTERPOLATED_POINT_METRICS%JACOBIAN_TYPE=0
        ELSE
          LOCAL_ERROR="The number of coordinate dimensions ("//TRIM(NUMBER_TO_VSTRING(NUMBER_OF_X_DIMENSIONS,"*",ERR,ERROR))// &
            & ") does not match the number of components of the interpolated point ("// &
            & TRIM(NUMBER_TO_VSTRING(SIZE(INTERPOLATED_POINT%VALUES,1),"*",ERR,ERROR))//")."
          CALL FLAG_ERROR(LOCAL_ERROR,ERR,ERROR,*998)
        ENDIF
      ENDIF
    ELSE
      CALL FLAG_ERROR("Interpolation point is not associated.",ERR,ERROR,*998)
    ENDIF

    CALL EXITS("FIELD_INTERPOLATED_POINT_METRICS_INITIALISE")
    RETURN
999 CALL FIELD_INTERPOLATED_POINT_METRICS_FINALISE(INTERPOLATED_POINT_METRICS,DUMMY_ERR,DUMMY_ERROR,*998)
998 CALL ERRORS("FIELD_INTERPOLATED_POINT_METRICS_INITIALISE",ERR,ERROR)
    CALL EXITS("FIELD_INTERPOLATED_POINT_METRICS_INITIALISE")
    RETURN 1
  END SUBROUTINE FIELD_INTERPOLATED_POINT_METRICS_INITIALISE

Ever taken a look at FORTRAN? Actually, I haven’t, either. FORTRAN is basically the oldest non-assembly language around, which is to say the oldest language where someone actually considered “what would programmers like to say?”, rather than “what should the machine be able to do?”

Also, this is FORTRAN 90, which is a much more recent update of FORTRAN. After a quick reading of the Wikipedia page, it looks like f90 (I’m just tired of writing in all caps) is the first update since 1977, which seems ancient but is in fact about halfway between the first invention of FORTRAN and the present day.

It removes many of the restrictions due to machine limitations (allowing free-form source code), and also allows recursive calls, something that the original FORTRAN didn’t—life is easy when you can statically allocate your stack frames!

It also has modules, and… gee whiz: dynamic allocation? Interesting: sounds like it would be much harder to compile f90 code into super-fast assembly than f77, but I suppose you’d have to ask an expert.

Hmmm… I wonder if there’s a formal semantics for more recent versions of Fortran 90? A quick google search suggests the answer is “no”. On the other hand, I’m not sure who would be interested in such a thing; you might be able to sell it as “this formal semantics could identify bugs in your optimization routines”. Anyone want to pay for this?

Okay, back to the source code. What’s going on here?

The first and most obvious thing here is that F90 clearly has a tradition of LONG_CAPITALIZED_VARIABLE_NAMES. COBOL had this going on too, and also an undergraduate classmate of mine named Celeste (RIP, no joke).

I personally find this fairly distracting; it means that a line of source code can’t contain more than two or three tokens, and means that computations have to be split over a whole bunch of lines. On the other hand, local variables apparently have to be declared at the top, so it’s hard to split a large computation into small ones by giving good names to intermediate values.

I think there’s a fairly large split in the world between people who believe that variables should be declared at the top of functions and those who believe that they should be able to appear anywhere; I think that the decls-only-at-top people are imperative people who are planning on doing all kinds of horrible mutation everywhere, and declaring things at the top is their way of preparing themselves for the horror below. The decls-anywhere people (can you tell which I am?), on the other hand, don’t mutate their bindings; these bindings are just a way of giving meaningful names to parts of computation, and there’s no need to hoist them all to the top.

So F90 has the pull toward decls-anywhere that stems from long identifier names, but it’s used by super-imperative people. How do they get any work done? Okay, now I’m just being snide. Sorry. I should point out here that Fortran is clearly one of the massive success stories of language design; it’s one of the first languages, and still in hugely widespread use, thanks in large part to the total 90-degree turn taken by the scientific computing community into C, which is simultaneously the fastest and least optimizable/maintainable language. See Fran Allen’s comments here! Sorry, off topic.

Other, more minor comments: the error-checking code following the dynamic allocation looks like it could easily be abstracted away, especially considering that the error messages aren’t parameterized over the context in any way that I can see.

Broadly speaking, I think I would make local declarations legal anywhere, and shorten up those variable names. Otherwise, looks nice!