Blog postings

COPEing with the Urban Coyote · by mark | 3 Jul 2023, 8:47 p.m.

I recently looked at my State Pension Forecast. There was a reasonably alarming statement 

  • Contracted Out Pension Equivalent (COPE)
  • Your COPE estimate is £x.yz a week

What is this? Well there was a bit of archaeology to do here. Below are my working notes. 

New State Pension

On 06 April 2016 the New State Pension came into force. You earn 1/35 of the full amount for every Qualifying Year (broadly, complete National Insurance year) you have after that date. Neat. But what about the older stuff? Well first you need to understand how the old stuff was calculated. This is the "starting amount" on to which very simple 1/35ths are added. 

Old State Pension

There was a myriad of older state pensions.

  • Basic State Pension - similar to New State Pension, pay NI for a year to get get an increment of this (was recently 30y for full accrual)
  • Graduated Retirement Benefit - ancient top-up pension that basically no-one gets and is so old I won't mention it again
  • State Earnings Related Pension Scheme - here is where it gets interesting. From 1978 through 2002, you earned, over a full working life, a 20% top up based on a band of earnings. A full working life was from age 16 to state pension age. 
  • State Second Pension - from 2002 through 2016, this was similar to SERPS but with different rules - e.g. a banded 40% / 10% / 20% accrual designed to make it more valuable for lower earners, eventually with flat rate accrual at the lower bands. 

You got NI Credits for some circumstances (e.g. staying in school for up to 3y after age 16). Also, you could "contract out" of SERPS and S2P in some circumstances, normally if you were in a defined benefit pension, where you paid lower NI and accrued no SERPS/S2P. This was the state subsidising your DB pension. 

To value your pre 06 Apr 2016 NI credits for state pension purposes, a few calculations are made. 

  • First, your old state pension + S2P + SERPS entitlements are calculated.
  • Second, your old state pension + S2P + SERPS entitlement is calculated as if you never contracted out and paid full NI instead. This is usually a bigger number. The difference between the first and second numbers is the COPE.
  • Third, your old years are applied to the new rules. So if you had 20 years prior to 2016, you get 20/35 as the old pension amount. The COPE is deducted as well. 

The larger of the first and third numbers is used. So, if you contracted out (you usually didn't have a choice), you paid less NI and the value of your pre 2016 NI years is lower than your post 2016 NI years. 

Combined

You have post 2016 years which give you 1/35 of the full new state pension amount. Your pre 2016 years can be worth more or less than 1/35 depending on whether you were paying lower NI via contracting out (but see your DB pension you got in exchange). If you were contracted in you could have old years worth more than 1/35 as you get additional credits for SERPS and S2P. 

The COPE, as far as I can tell, only applies to the pre 2016 years. It is an adjustment applied to the starting amount for the years you were paying less NI. You can still earn up to the max by adding more qualifying years of NI. 

I tried calculating my COPE from my own incomplete records. Remarkably I get very close (within 1%). Issues:

Gotchas

The NI rebate for contracting out was flat rate but the S2P foregone was not. So if you earned below the breakeven point, you actually accrued a sliver of S2P to reflect that S2P was proportionately more valuable than the NI rebate below this level of earnings. The level of the sliver is the gap between SERPS style 20% accrual and S2P nonlinear accrual.

After some point the percentage of earnings accruals were replaced by flat rate accruals for the benefit of low earners and the scheme overall became less generous. 

You have to look up the revlaution of earnings order to adjust from the 2015/16 value to the latest value if you want to match the number shown on the state pension forecast. 

I've put together the following table of magic numbers you can use if you want for S2P calcs. 

Tax year LEL LET SET UEL UAP Flat Rate
2002/03 3,900 10,800 24,600 30,420    
2003/04 4,004 11,200 25,600 30,940    
2004/05 4,108 11,600 26,600 31,720    
2005/06 4,264 12,100 27,800 32,760    
2006/07 4,368 12,500 28,800 33,540    
2007/08 4,524 13,000 30,000 34,840    
2008/09 4,680 13,500 31,100 40,040 40,040  
2009/10 4,940 13,900 31,800 43,875 40,040  
2010/11 5,044 14,100 32,200 43,875 40,040  
2011/12 5,304 14,400 32,600 42,475 40,040  
2012/13 5,564 14,700 33,000 42,475 40,040 88.40
2013/14 5,668 15,000 33,700 41,450 40,040 91.00
2014/15 5,772 15,100 33,800 41,865 40,040 92.00
2015/16 5,824 15,300 34,300 42,385 40,040 93.60

Up to 2010, you got 40% on LEL to LET, 10% on LET to SET and then 20% on SET to UEL (UAP for last two years). For 2010/11 and 2011/12, you got 40% for LEL-LET and 10% up to the UAP. For the last stretch, you got the flat rate for any earnings above LEL and then 10% on LET-UAP. This is based on lifetime earnings, which are from age 16 to state pension age. You get 1/(state pension age - 16) times accrual.

There are arcane indexing rules - you need to revalue to 2015/16 amounts, calculate, and then revalue to current tax year. 

 

My cat disclaims responsibility · by mark | 17 Mar 2023, 1:16 p.m.

I didn't do it

Cosmos the feline wrecking ball

 

Flex and Line Endings · by mark | 5 Mar 2023, 11:52 a.m. (updated 5 Mar 2023, 11:53 a.m.)

I said some time ago I'd write about how I got line endings working. This is that post. 

There are three problems with Flex newlines:

  • Windows
  • Line counts
  • Posix line definition

Windows

Windows isses come from the fact that Flex is primarily a Unix tool so expects lines to end \n. But if you read Windows files you get \r\n. You can possibly get \r or even \n\r if you read files from old Macs or old BBC Micros, somehow. The Flex issue is then telling it how to handle Windows line endings. It is actually straightforward. You have a rule

(\n|\r\n?)

which will catch Unix line endings, Windows line endings or old Mac line endings. I last used a BBC Micro in 2001 as part of a sixth year project (they had a pH probe that was connected to a BBC micro), so I am not interested in reading those files. But it could be adapted. In practice Unix and Windows line endings are all you need. The only other one in common use is mainframe but you won't likely see one of these files as a normal person, because the people that own them go to great lengths to hide EBCDIC from you. 

An alternative is just to consume \r with an empty action and let the trailing \n drive any actions. But I have a small handful of mac files I need to deal with. Finally you can have two versions of your program for the different line endings. QIFs are just plain ASCII so the control codes only appear where they should. 

Line counts

This is probably the nastiest part of the whole thing as you really need to update the column count as well. If you are not insane you are using Bison's complete symbols which provide a location type. So "all" you have to do is update this with every token. And if you are using complete symbols you define your own parsing context type that is passed to the lexer. This means you can access the context (i.e., the embedded location object) in every action. Phew! 

Your context object will look like this:

#pragma once
#include "location.hh"

namespace my_ns {

    class Context // again more like a struct
    {
    public:
        Context() : done(false) { loc.initialize(); }
        bool done;               // set to true at EOF
        std::unique_ptr node;    // each lexeme is actually a tree node
        location loc;            // bison provided location class
    };

}

and your lexer call declarion for flex will be

#define YY_DECL my_ns::Parser::symbol_type my_ns::Scanner::lex(my_ns::Context *context)

You will need a custom user action that ensures consumed characters are reflected in the location; this goes immediately after the preceding

#define YY_USER_ACTION context->loc.step(); context->loc.columns(yyleng);

and finally your new line reader updates the line counter when it is touched:

(\n|\r\n?) { context->loc.lines(); return my_ns::Parser::make_ENDL(context->loc); }

Phew. The YY_USER_ACTION gets performed for every match so that, even if you discard characters, the location is correct. You have to be very careful with newline matching; anything that could possibly match a newline isn't good enough, your patterns either always contain newlines or they never contain newlines. 

Posix

Posix declares that every line ends with a newline. In practice, many last lines end with an EOF not a newline. What do? Flex lets you match an EOF and you can use a push parser approach so that a raw EOF is always turned into a newline and an EOF. You can track whether the last thing was a newline in the context. But in reality it is better handled in the grammar. If there are only a small number (possibly one or two) tokens that a legally constructed file, modulo terminal newline, can end on then you can use the Bison pseudotoken YYEOF to say "EOF acceptable". For example, QIF files always end in a record separator ^ but this is not always a well formed POSIX line. So the bison rule is

separator_row: SEPARATOR ENDL | SEPARATOR YYEOF; 

where separator is just the ^ character. This means a file can end in any number (including zero) of newlines (including windows new lines) as long as the last record includes a record separator at the end. Injecting optional newlines via flex into the token stream can be done but it is very irrating and ugly. Bison does the right thing with end of files (i.e. it'll reduce as much as it can), so you can generally forget about the end of file marker except if you need to catch optional end of lines. 

The context class above contains a bit that can be used to tell Bison that the EOF flex returned is an actual EOF if you are doing something interesting like an interpreter (where you use EOFs to capture line endings, making Bison reduce the input and execute it). It is easy to set this. It is already initialised to false, so to make it true:

<<EOF>> { context->done = true; return my_ns::Parser::make_YYEOF(context->loc); }

What happens in interpreters is that newlines are used to make a YYEOF which causes bison to reduce the input (this almost always means evaluate the syntax tree) and return from yyparse(). The thing that called yyparse() will examine the context to see if flex actually reached the end of input or not. If it is just a newline and not a "real" EOF the calling routine loops. 

This is what command line interpreters really do - basically loop over a fancy tree building and reduction routine. The context can hold symbol tables etc which allows things to persist between bison calls. Neat!

 

This was a pleasant sunset · by mark | 19 Feb 2023, 8:22 p.m.

Feels like winter is drawing to a close. But what about second winter?

Margate this evening

 

Doing a hike up in Lauvåsen · by mark | 20 Jan 2023, 7:15 a.m.

In Norway there are mountain huts you are allowed to just use. Similar to bothies in the UK, but while bothies are in very remote places to stop people doing arson on them you can get to et hytte reasonably easily. I went to the one near Fister. There is a waymarked path up the mountain behind the school and you basically keep going up. Quite steep but also only a few km and the views are wonderful. 

Here are some images. 

Fisterbu mountain hut

The hut itself. Plonked on top of a mountain. Some of them are delivered by helicopter in sections and put together. Note the frost clinging to things, it was quite cold. 

Looking over the shoulder of fisterbu

First hints of the view keeking over the shoulder of the hut. In summer I can imagine this gets rammed with people drinking 39NOK beers 

Looking down on Fister

I walked up to the edge and took this. This is the village / townlet of Fister north of Stavanger. View is just so nice. At the top they have a wee book you can fill in to say "I was here". It's in a sealed metal trap thing with a pen. "Jeg kommer fra Skottland til her". 

Turned left 90 degrees or pi/2 radians

Now looking towards the sun but still over Fister (just). This was wonderful. Very calming. Much relax. Little heat. 

And some fire

The hut had a fireplace in it. We brought some logs and immolated them in the approprirate place. You'd need to get through maybe six or seven logs to fully warm the place up. We only brought three which did take the edge off but it was still cold inside. I just find it astonishing that the huts are allowed to exist; someone would wreck them in the UK.