Blog postings
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.
I didn't do it

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!
Feels like winter is drawing to a close. But what about second winter?

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.
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.
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
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".
Now looking towards the sun but still over Fister (just). This was wonderful. Very calming. Much relax. Little heat.
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.