Task: Continued fraction_Arithmetic_G(matrix ng, continued fraction n1, continued fraction n2)


C++: 
class NG_8 : public matrixNG {
  private: int a12, a1, a2, a, b12, b1, b2, b, t;
           double ab, a1b1, a2b2, a12b12;
  const int chooseCFN(){return fabs(a1b1-ab) > fabs(a2b2-ab)? 0 : 1;}
  const bool needTerm() {
    if (b1==0 and b==0 and b2==0 and b12==0) return false;
    if (b==0){cfn = b2==0? 0:1; return true;} else ab = ((double)a)/b;
    if (b2==0){cfn = 1; return true;} else a2b2 = ((double)a2)/b2;
    if (b1==0){cfn = 0; return true;} else a1b1 = ((double)a1)/b1;
    if (b12==0){cfn = chooseCFN(); return true;} else a12b12 = ((double)a12)/b12;
    thisTerm = (int)ab;
    if (thisTerm==(int)a1b1 and thisTerm==(int)a2b2 and thisTerm==(int)a12b12){
      t=a; a=b; b=t-b*thisTerm; t=a1; a1=b1; b1=t-b1*thisTerm; t=a2; a2=b2; b2=t-b2*thisTerm; t=a12; a12=b12; b12=t-b12*thisTerm;
      haveTerm = true; return false;
    }
    cfn = chooseCFN();
    return true;
  }
  void consumeTerm(){if(cfn==0){a=a1; a2=a12; b=b1; b2=b12;} else{a=a2; a1=a12; b=b2; b1=b12;}}
  void consumeTerm(int n){
    if(cfn==0){t=a; a=a1; a1=t+a1*n; t=a2; a2=a12; a12=t+a12*n; t=b; b=b1; b1=t+b1*n; t=b2; b2=b12; b12=t+b12*n;}
    else{t=a; a=a2; a2=t+a2*n; t=a1; a1=a12; a12=t+a12*n; t=b; b=b2; b2=t+b2*n; t=b1; b1=b12; b12=t+b12*n;}
  }
  public:
  NG_8(int a12, int a1, int a2, int a, int b12, int b1, int b2, int b): a12(a12), a1(a1), a2(a2), a(a), b12(b12), b1(b1), b2(b2), b(b){
}};



Go: package cf

import "math"



















type NG8 struct {
	A12, A1, A2, A int64
	B12, B1, B2, B int64
}


var (
	NG8Add = NG8{0, 1, 1, 0, 0, 0, 0, 1}
	NG8Sub = NG8{0, 1, -1, 0, 0, 0, 0, 1}
	NG8Mul = NG8{1, 0, 0, 0, 0, 0, 0, 1}
	NG8Div = NG8{0, 1, 0, 0, 0, 0, 1, 0}
)

func (ng *NG8) needsIngest() bool {
	if ng.B12 == 0 || ng.B1 == 0 || ng.B2 == 0 || ng.B == 0 {
		return true
	}
	x := ng.A / ng.B
	return ng.A1/ng.B1 != x || ng.A2/ng.B2 != x && ng.A12/ng.B12 != x
}

func (ng *NG8) isDone() bool {
	return ng.B12 == 0 && ng.B1 == 0 && ng.B2 == 0 && ng.B == 0
}

func (ng *NG8) ingestWhich() bool { 
	if ng.B == 0 && ng.B2 == 0 {
		return true
	}
	if ng.B == 0 || ng.B2 == 0 {
		return false
	}
	x1 := float64(ng.A1) / float64(ng.B1)
	x2 := float64(ng.A2) / float64(ng.B2)
	x := float64(ng.A) / float64(ng.B)
	return math.Abs(x1-x) > math.Abs(x2-x)
}

func (ng *NG8) ingest(isN1 bool, t int64) {
	if isN1 {
		
		
		ng.A12, ng.A1, ng.A2, ng.A,
			ng.B12, ng.B1, ng.B2, ng.B =
			ng.A2+ng.A12*t, ng.A+ng.A1*t, ng.A12, ng.A1,
			ng.B2+ng.B12*t, ng.B+ng.B1*t, ng.B12, ng.B1
	} else {
		
		
		ng.A12, ng.A1, ng.A2, ng.A,
			ng.B12, ng.B1, ng.B2, ng.B =
			ng.A1+ng.A12*t, ng.A12, ng.A+ng.A2*t, ng.A2,
			ng.B1+ng.B12*t, ng.B12, ng.B+ng.B2*t, ng.B2
	}
}

func (ng *NG8) ingestInfinite(isN1 bool) {
	if isN1 {
		
		
		ng.A2, ng.A, ng.B2, ng.B =
			ng.A12, ng.A1,
			ng.B12, ng.B1
	} else {
		
		
		ng.A1, ng.A, ng.B1, ng.B =
			ng.A12, ng.A2,
			ng.B12, ng.B2
	}
}

func (ng *NG8) egest(t int64) {
	
	
	ng.A12, ng.A1, ng.A2, ng.A,
		ng.B12, ng.B1, ng.B2, ng.B =
		ng.B12, ng.B1, ng.B2, ng.B,
		ng.A12-ng.B12*t, ng.A1-ng.B1*t, ng.A2-ng.B2*t, ng.A-ng.B*t
}





func (ng NG8) ApplyTo(N1, N2 ContinuedFraction, limit int) ContinuedFraction {
	return func() NextFn {
		next1, next2 := N1(), N2()
		done := false
		sinceEgest := 0
		return func() (int64, bool) {
			if done {
				return 0, false
			}
			for ng.needsIngest() {
				sinceEgest++
				if sinceEgest > limit {
					done = true
					return 0, false
				}
				isN1 := ng.ingestWhich()
				next := next2
				if isN1 {
					next = next1
				}
				if t, ok := next(); ok {
					ng.ingest(isN1, t)
				} else {
					ng.ingestInfinite(isN1)
				}
			}
			sinceEgest = 0
			t := ng.A / ng.B
			ng.egest(t)
			done = ng.isDone()
			return t, true
		}
	}
}