func (p *Program) Add(i, j int) (int, error) {
	if err := p.boundscheck(i); err != nil {
		return 0, err
	}
	if err := p.boundscheck(j); err != nil {
		return 0, err
	}
	*p = append(*p, Op{i, j})
	return len(*p), nil
}
Add appends an operation that adds indices i and j. Returns the index of the
result.
package addchain
import (
	"fmt"
	"math/big"
	"github.com/mmcloughlin/addchain/internal/bigint"
)
type Op struct{ I, J int }
func (o Op) IsDouble() bool { return o.I == o.J }
func (o Op) Operands() []int {
	if o.IsDouble() {
		return []int{o.I}
	}
	return []int{o.I, o.J}
}
func (o Op) Uses(i int) bool {
	return o.I == i || o.J == i
}
type Program []Op
func (p *Program) Shift(i int, s uint) (int, error) {
	for ; s > 0; s-- {
		next, err := p.Double(i)
		if err != nil {
			return 0, err
		}
		i = next
	}
	return i, nil
}
func (p *Program) Double(i int) (int, error) {
	return p.Add(i, i)
}