Archive for October, 2012

STEP Actions

October 16, 2012

I’ve started adding actions to the STEP code, targeted (at least at first) at collecting up the entity instance names in a parameter list to make it easier to analyze what’s in a STEP file.

I need to do this more often, because I spent about an hour fumbling about making stupid mistakes. And even now that I’ve got it working, I’m haunted by the notion there should be a simpler approach. Anyway, here’s what I’ve got at the moment:

class ISO_10303_21::Actions {
    method entity_instance_name($/) { make [~$/] }
    method parameter($/) {
        for <typed_parameter untyped_parameter omitted_parameter> -> $s {
            return make $/{$s}.ast if $/{$s}.defined;
        }
    }
    method omitted_parameter($/) { make [] }
    method untyped_parameter($/) {
        for <entity_instance_name list_of_parameters> -> $s {
            return make $/{$s}.ast if $/{$s}.defined;
        }
        make [];
    }
    method typed_parameter($/) { make $<parameter>.ast }
    method list_of_parameters($/) { make merge-arrays(@($<parameter>)».ast); }
    method parameter_list($/) { make merge-arrays(@($<parameter>)».ast); }
}

What’s bugging me are the parameter and untyped_parameter definitions — those seem like they should be easier to express somehow. At least, that basic functionality is going to be pretty common.

Oh, and I just found (and fixed) a bug in the code looking at this blog post.

Feel like I had something more to say, but I’m tired and heading to bed.

Parsing STEP

October 10, 2012

A month ago I started perl6-ISO_10303-21. In plain English, it’s the beginnings of a toolset for working with CAD files in the STEP format. All it does is parse so far.

The STEP (that’s ISO-10303) Part 21 standard provides a BNF (I think) grammar for ASCII STEP files. It was downright trivial to translate it to a Perl 6 grammar — looking at the commits, it took me about two days to get it to read the first file. THen it sat there for a long time until I starting throwing files at it.

Since then I’ve made a couple of simple changes. First, I replace C-style comments in the file with spaces before parsing; the spec’s grammar doesn’t mention them at all.

Second, I discovered three of the basic sample files I was using were actually illegal, with newlines embedded in strings. I fretted about what to do for a while: should I expand the grammar to accept illegal but “standard” files, or keep the grammar strict so that I could use it to test files my own code exports for correctness?

Then I realized I could have my cake and eat it too:

grammar ISO_10303_21::LooseGrammar is ISO_10303_21::Grammar {
    token non_q_char { <special> | <digit> | <space> | <lower> | <upper> | \v }
}

I just defined a new subclass, changing the non_q_char token to also accept vertical whitespaces, too. Now ISO_10303_21::Grammar is strict, and ISO_10303_21::LooseGrammar is loose.

The next obstacle I’ve run into was speed. The 1.3 meg sample file took about five minutes to prase in Rakudo, and 10+ hours (!) in Niecza. Luckily jnthn++ was on the job, and sent me a patch about fifteen minutes after I sent him the profile of the parse today. (Rakudo’s got --profile built in.) That shaved off 1/6th of the running time.

He also pointed out that tokens like

token standard_keyword { <upper> [ <upper> | <digit> ]* }

were unnecessarily creating a Match object for each character in the keyword. Since all we want is the full text of the keyword, this could be changed to

token standard_keyword { <.upper> [ <.upper> | <.digit> ]* }

and it would suppress those Match objects. That reduced the running time by another 10%.

Another few days like this and it will be fast enough to do some useful work for me…

Sums of Fourth Powers

October 5, 2012

Another fun John Cook post has sent me off into playing with numbers and Perl 6.

He gives a footnote saying that Euler discovered 635318657 = 158^4 + 59^4 = 134^4 + 133^4 and that this was the smallest number known to be the sum of two fourth powers in two ways. It seems odd now to think of such questions being unresolved. Today we’d ask Hardy “What do you mean 635318657 is the smallest known example? Why didn’t you write a little program to find out whether it really is the smallest?”

Perl 6 has features that make that fun to explore, so let’s go to it! Here was my first attempt:

my @fourth-powers = (1..*).map(* ** 4) ...^ * > 635318657;
my %counts;
for @fourth-powers X+ @fourth-powers -> $sum {
    %counts{$sum}++;
}

for %counts.keys.grep({ %counts{$_} > 2 }) -> $sum {
    say "$sum has { %counts{$sum} / 2 } fourth power sums";
}

This works, and is quite fast in Niecza. (It’s much slower in Rakudo for some reason, though it still finishes in about ten seconds.) I love that first line, which constructs a lazy infinite list of fourth powers, then truncates it at 635318657. Then it uses X+ to build all the sums of two fourth powers less than (or equal to) 635318657. The rest of the code is pretty mundane, I fear.

I decided to try to use classify to get rid of the explicit loops, resulting in this code:

my @fourth-powers = (1..*).map(* ** 4) ...^ * > 635318657;
my @results = (@fourth-powers X+ @fourth-powers).classify({ $_ }).pairs.grep(*.value > 2);
say @results.map({ $_.key ~ " " ~ $_.value.Int / 2 ~ " times" });

Unfortunately, this doesn’t work in Niecza. So now I’ve got some bugs to fix…


Follow

Get every new post delivered to your Inbox.