#include <perms.h>
// reals long
int _imp_mainep(int _imp_argc, char **_imp_argv) {
  _imp_enter();  // %begin
  int ALINE;
  int BLINE;
  int CLINE;
  int DLINE;
  int ELINE;
  int FLINE;
  int GPRIMELINE;
  int HLINE;
  //              h line
  double SPECTRALLINE[8 - 1 + 1];
  //     %real %array spectral line(1:8)
  int CURRENTSURFACES;
  //     %integer current surfaces
  double TESTCASE[4 - 1 + 1][4 - 1 + 1];
  //     %real %array test case(1:4, 1:4)
  int CURVATURERADIUS;
  int INDEXOFREFRACTION;
  int DISPERSION;
  int EDGETHICKNESS;
  double CLEARAPERTURE;
  double ABERRLSPHER;
  double ABERROSC;
  double ABERRLCHROM;
  double MAXLSPHER;
  double MAXOSC;
  double MAXLCHROM;
  double RADIUSOFCURVATURE;
  double OBJECTDISTANCE;
  double RAYHEIGHT;
  double AXISSLOPEANGLE;
  double FROMINDEX;
  double TOINDEX;
  int NUMBEROFITERATIONS;
  int ITERATION;
  //     %integer number of iterations, iteration
  int PARAXIAL;
  int MARGINALRAY;
  int PARAXIALRAY;
  //     %integer paraxial, marginal ray, paraxial ray
  int ODFIELD;
  int SAFIELD;
  //     %integer od field, sa field
  double ODSA[2 - 1 + 1][2 - 1 + 1];
  //     %real %array od sa(1:2, 1:2)
  double ODCLINE;
  double ODFLINE;
  //     %real od cline, od fline
  auto double COT(double X) {
    _imp_enter();
    //     %real %fn cot(%real x)
    return (/*ERROR: name_sym_idx is -1!*/ /*C_NAME*/
            /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ 1.0 /
            (() / ()));  //         %result = 1.0 / (sin(x) / cos(x))

    _imp_leave();
  }
  //     %end {cot}
  auto double ARCSIN(double X) {
    _imp_enter();
    //     %real %fn arc sin(%real x)
    return (/*ERROR: name_sym_idx is -1!*/ /*C_NAME*/
            /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ 2 *
            ());  //         %result = 2 * arc tan1(x / (1 + sqrt(1 - x^2)))

    _imp_leave();
  }
  //     %end {arc sin}
  auto void OUTBIGREAL(int CHANNEL, double X) {
    _imp_enter();
    //     %routine out big real(%integer channel, %real x)
    double FRACTION;
    //         %real fraction
    FRACTION = X;  //         fraction = x

    _imp_leave();
  }
  //     %end {out big real}
  auto void TRANSITSURFACE(void) {
    _imp_enter();
    //     %routine transit surface
    double IANG;
    double RANG;
    double IANGSIN;
    double RANGSIN;
    double OLDAXISSLOPEANGLE;
    double SAGITTA;
    if (PARAXIAL == PARAXIALRAY) {
      //         %if paraxial = paraxial ray %then %start
      if (RADIUSOFCURVATURE != 0) {
        //             %if radius of curvature # 0 %then %start
        if (OBJECTDISTANCE == 0) {
          //                 %if object distance = 0 %then %start
          AXISSLOPEANGLE = 0;  //                     axis slope angle = 0
          IANGSIN =
              RAYHEIGHT /
              RADIUSOFCURVATURE;  //                     iang sin = ray height /
                                  //                     radius of curvature

        } else
          IANGSIN = ((OBJECTDISTANCE - RADIUSOFCURVATURE) / RADIUSOFCURVATURE) *
                    AXISSLOPEANGLE;  //        %finish %else
        //            iang sin = ((object distance - radius of curvature) /
        //            radius of curvature) * axis slope angle
        RANGSIN = (FROMINDEX / TOINDEX) *
                  IANGSIN;  //                 rang sin = (from index / to
                            //                 index) * iang sin
        OLDAXISSLOPEANGLE =
            AXISSLOPEANGLE;  //                 old axis slope angle = axis
                             //                 slope angle
        AXISSLOPEANGLE = AXISSLOPEANGLE + IANGSIN -
                         RANGSIN;  //        axis slope angle = axis slope angle
                                   //        + iang sin - rang sin
        if (OBJECTDISTANCE != 0)
          RAYHEIGHT =
              OBJECTDISTANCE *
              OLDAXISSLOPEANGLE;  //        %if object distance # 0 %then ray
                                  //        height = object distance * old axis
                                  //        slope angle
        OBJECTDISTANCE =
            RAYHEIGHT /
            AXISSLOPEANGLE;  //                 object distance = ray height /
                             //                 axis slope angle

      } else {  //             %else
        OBJECTDISTANCE =
            OBJECTDISTANCE *
            (TOINDEX /
             FROMINDEX);  //                 object distance = object distance *
                          //                 (to index / from index)
        AXISSLOPEANGLE =
            AXISSLOPEANGLE *
            (FROMINDEX /
             TOINDEX);  //                 axis slope angle = axis slope angle *
                        //                 (from index / to index)
      }                 //             %finish

    } else {  //         %else
      if (RADIUSOFCURVATURE != 0) {
        //             %if radius of curvature # 0 %then %start
        if (OBJECTDISTANCE == 0) {
          //                 %if object distance = 0 %then %start
          AXISSLOPEANGLE = 0;  //                     axis slope angle = 0
          IANGSIN =
              RAYHEIGHT /
              RADIUSOFCURVATURE;  //                     iang sin = ray height /
                                  //                     radius of curvature

        } else /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/
          IANGSIN = ((OBJECTDISTANCE - RADIUSOFCURVATURE) / RADIUSOFCURVATURE) *
                    ();  //        %finish %else iang sin = ((object distance -
                         //        radius of curvature) / radius of curvature) *
                         //        sin(axis slope angle)
        IANG = ARCSIN(IANGSIN);  //                 iang = arc sin(iang sin)
        RANGSIN = (FROMINDEX / TOINDEX) *
                  IANGSIN;  //                 rang sin = (from index / to
                            //                 index) * iang sin
        OLDAXISSLOPEANGLE =
            AXISSLOPEANGLE;  //                 old axis slope angle = axis
                             //                 slope angle
        AXISSLOPEANGLE =
            AXISSLOPEANGLE + IANG -
            ARCSIN(RANGSIN);  //        axis slope angle = axis slope angle +
                              //        iang - arcsin(rang sin)
        /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ SAGITTA =
            2 * RADIUSOFCURVATURE *
            (REXP(, 2));  // sagitta = 2 * radius of curvature * (sin((old axis
                          // slope angle + iang) / 2) ^ 2)
        /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ OBJECTDISTANCE =
            ((RADIUSOFCURVATURE * ()) * COT(AXISSLOPEANGLE)) +
            SAGITTA;  //    object distance = ((radius of curvature * sin(old
                      //    axis slope angle + iang)) * cot(axis slope angle)) +
                      //    sagitta

      } else {  //             %else
        /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ RANG =
            -ARCSIN((FROMINDEX / TOINDEX) *
                    ());  //        rang = -arcsin((from index / to index) *
                          //        sin(axis slope angle))
        /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ /*ERROR: name_sym_idx is -1!*/
        /*C_NAME*/ OBJECTDISTANCE =
            OBJECTDISTANCE *
            ((TOINDEX * ()) /
             (FROMINDEX * ()));  //        object distance = object distance *
                                 //        ((to index * cos(-rang)) / (from
                                 //        index * cos(axis slope angle)))
        AXISSLOPEANGLE = -RANG;  //                 axis slope angle = -rang
      }                          //             %finish
    }                            //         %finish

    _imp_leave();
  }
  //     %end {transit surface}
  auto void TRACELINE(int LINE, double RAYH) {
    _imp_enter();
    //     %routine trace line(%integer line, %real ray h)
    int I;
    //         %integer i
    OBJECTDISTANCE = 0;  //         object distance = 0
    RAYHEIGHT = RAYH;    //         ray height = ray h
    FROMINDEX = 1;       //         from index = 1
    for (I = 1; I != CURRENTSURFACES + 1; I += 1) {
      //         %for i = 1, 1, current surfaces %cycle
      RADIUSOFCURVATURE =
          TESTCASE[I]
                  [CURVATURERADIUS];  //             radius of curvature = test
                                      //             case(i, curvature radius)
      TOINDEX =
          TESTCASE[I]
                  [INDEXOFREFRACTION];  //             to index = test case(i,
                                        //             index of refraction)
      if (TOINDEX > 1)
        TOINDEX =
            TOINDEX +
            ((SPECTRALLINE[DLINE] - SPECTRALLINE[LINE]) /
             (SPECTRALLINE[CLINE] - SPECTRALLINE[FLINE])) *
                ((TESTCASE[I][INDEXOFREFRACTION] - 1.0) /
                 TESTCASE[I]
                         [DISPERSION]);  //    %if to index > 1 %then to index =
                                         //    to index + ((spectral line(d
                                         //    line) - spectral line(line)) /
                                         //    (spectral line(c line) - spectral
                                         //    line(f line))) * ((test case(i,
                                         //    index of refraction) - 1.0) /
                                         //    test case(i, dispersion))
      TRANSITSURFACE();                  //             transit surface
      FROMINDEX = TOINDEX;               //             from index = to index
      if (I < CURRENTSURFACES)
        OBJECTDISTANCE =
            OBJECTDISTANCE -
            TESTCASE[I][EDGETHICKNESS];  //    %if i < current surfaces %then
                                         //    object distance = object distance
                                         //    - test case(i, edge thickness)
    }
    //         %repeat

    _imp_leave();
  }
  //     %end {trace line}
  // END GLOBAL DECLARATONS
  //     %comment END GLOBAL DECLARATONS
  // Spectral lines
  //     %comment Spectral lines
  ALINE = 1;
  BLINE = 2;
  CLINE = 3;
  DLINE = 4;  //     a line = 1; b line = 2; c line = 3; d line = 4
  ELINE = 5;
  FLINE = 6;
  GPRIMELINE = 7;  //         e line = 5; f line = 6; g prime line = 7
  HLINE = 8;       //         h line = 8
  SPECTRALLINE[ALINE] = 7621.0;    //     spectral line(a line)       = 7621.0
  SPECTRALLINE[BLINE] = 6869.955;  //     spectral line(b line)       = 6869.955
  SPECTRALLINE[CLINE] =
      6562.8160;  //     spectral line(c line)       = 6562.8160
  SPECTRALLINE[DLINE] = 5895.944;  //     spectral line(d line)       = 5895.944
  SPECTRALLINE[ELINE] = 5269.557;  //     spectral line(e line)       = 5269.557
  SPECTRALLINE[FLINE] = 4861.344;  //     spectral line(f line)       = 4861.344
  SPECTRALLINE[GPRIMELINE] =
      4340.477;                    //     spectral line(g prime line) = 4340.477
  SPECTRALLINE[HLINE] = 3968.494;  //     spectral line(h line)       = 3968.494
  //  Initialise the test case array
  //     %comment  Initialise the test case array
  CURRENTSURFACES = 4;  //     current surfaces = 4
  CURVATURERADIUS = 1;
  INDEXOFREFRACTION = 2;
  DISPERSION =
      3;  //     curvature radius = 1; index of refraction = 2; dispersion = 3
  EDGETHICKNESS = 4;  //         edge thickness = 4
  TESTCASE[1][CURVATURERADIUS] =
      27.05;  //     test case(1, curvature radius)    =   27.05
  TESTCASE[1][INDEXOFREFRACTION] =
      1.5137;  //     test case(1, index of refraction) =    1.5137
  TESTCASE[1][DISPERSION] =
      63.6;  //     test case(1, dispersion)          =   63.6
  TESTCASE[1][EDGETHICKNESS] =
      0.52;  //     test case(1, edge thickness)      =    0.52
  TESTCASE[2][CURVATURERADIUS] =
      -16.68;  //     test case(2, curvature radius)    =  -16.68
  TESTCASE[2][INDEXOFREFRACTION] =
      1.0;  //     test case(2, index of refraction) =    1.0
  TESTCASE[2][DISPERSION] = 0.0;  //     test case(2, dispersion)          = 0.0
  TESTCASE[2][EDGETHICKNESS] =
      0.138;  //     test case(2, edge thickness)      =    0.138
  TESTCASE[3][CURVATURERADIUS] =
      -16.68;  //     test case(3, curvature radius)    =  -16.68
  TESTCASE[3][INDEXOFREFRACTION] =
      1.6164;  //     test case(3, index of refraction) =    1.6164
  TESTCASE[3][DISPERSION] =
      36.7;  //     test case(3, dispersion)          =   36.7
  TESTCASE[3][EDGETHICKNESS] =
      0.38;  //     test case(3, edge thickness)      =    0.38
  TESTCASE[4][CURVATURERADIUS] =
      -78.1;  //     test case(4, curvature radius)    =  -78.1
  TESTCASE[4][INDEXOFREFRACTION] =
      1.0;  //     test case(4, index of refraction) =    1.0
  TESTCASE[4][DISPERSION] = 0.0;  //     test case(4, dispersion)          = 0.0
  TESTCASE[4][EDGETHICKNESS] =
      0.0;  //     test case(4, edge thickness)      =    0.0
  MARGINALRAY = 1;
  PARAXIALRAY = 2;  //     marginal ray = 1; paraxial ray = 2
  ODFIELD = 1;
  SAFIELD = 2;  //     od field = 1; sa field = 2
  //  number of iterations = 40263820;
  //     %comment  number of iterations = 40263820;
  NUMBEROFITERATIONS = 1;  //     number of iterations = 1
  CLEARAPERTURE = 4;       //     clear aperture = 4
  for (ITERATION = 1; ITERATION != NUMBEROFITERATIONS + 1; ITERATION += 1) {
    //     %for iteration = 1, 1, number of iterations %cycle
    for (PARAXIAL = MARGINALRAY; PARAXIAL != PARAXIALRAY + 1; PARAXIAL += 1) {
      //         %for paraxial = marginal ray, 1, paraxial ray %cycle
      TRACELINE(DLINE,
                CLEARAPERTURE /
                    2);  //             trace line(d line, clear aperture / 2)
      ODSA[PARAXIAL][ODFIELD] =
          OBJECTDISTANCE;  //             od sa(paraxial, od field) = object
                           //             distance
      ODSA[PARAXIAL][SAFIELD] =
          AXISSLOPEANGLE;  //             od sa(paraxial, sa field) = axis slope
                           //             angle
    }
    //         %repeat
    // Trace marginal ray in C
    //         %comment Trace marginal ray in C
    PARAXIAL = MARGINALRAY;  //         paraxial = marginal ray
    TRACELINE(CLINE, CLEARAPERTURE /
                         2);   //         trace line(c line, clear aperture / 2)
    ODCLINE = OBJECTDISTANCE;  //         od cline = object distance
    // Trace marginal ray in F
    //         %comment Trace marginal ray in F
    TRACELINE(FLINE, CLEARAPERTURE /
                         2);   //         trace line(f line, clear aperture / 2)
    ODFLINE = OBJECTDISTANCE;  //         od fline = object distance
    ABERRLSPHER = ODSA[PARAXIALRAY][ODFIELD] -
                  ODSA[MARGINALRAY]
                      [ODFIELD];  //    aberr lspher = od sa(paraxial ray, od
                                  //    field) - od sa(marginal ray, od field)
                                  // !
    // ! WARNING: the %c is making it through to 'c', presumably as white space?
    // Find and fix.
    // !
    /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ ABERROSC =
        1 -
        ((ODSA[PARAXIALRAY][ODFIELD] * ODSA[PARAXIALRAY][SAFIELD]) /
         (() * ODSA[MARGINALRAY]
                   [ODFIELD]));  //  aberr osc = 1 - ((od sa(paraxial ray, od
                                 //  field) * od sa(paraxial ray, sa field)) /
                                 //  (sin(od sa(marginal ray, sa field)) * od
                                 //  sa(marginal ray, od field)))
    ABERRLCHROM =
        ODFLINE - ODCLINE;  //         aberr lchrom = od fline - od cline
    /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/ MAXLSPHER =
        0.0000926 / REXP(, 2);  //         max lspher = 0.0000926 / sin(od
                                //         sa(marginal ray, sa field)) ^ 2
    MAXLCHROM = MAXLSPHER;      //         max lchrom = max lspher
    MAXOSC = 0.0025;            //         max osc = 0.0025

  }
  //     %repeat
  // Print the analysis of the ray trace
  //     %comment Print the analysis of the ray trace
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     Marginal ray    "))
  OUTBIGREAL(1, ODSA[MARGINALRAY][ODFIELD]);  //     outbigreal(1, od
                                              //     sa(marginal ray, od field))
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     "))
  PRINT(ODSA[MARGINALRAY][SAFIELD], 5, 11);
  NEWLINE();  //     print(od sa(marginal ray, sa field), 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     Paraxial ray    "))
  OUTBIGREAL(1, ODSA[PARAXIALRAY][ODFIELD]);  //     outbigreal(1, od
                                              //     sa(paraxial ray, od field))
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     "))
  PRINT(ODSA[PARAXIALRAY][SAFIELD], 5, 11);
  NEWLINE();  //     print(od sa(paraxial ray, sa field), 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("Longitudinal
                                              //     spherical aberration: "))
  PRINT(ABERRLSPHER, 5, 11);
  NEWLINE();  //     print(aberr lspher, 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     (Maximum permissible): "))
  PRINT(MAXLSPHER, 5, 11);
  NEWLINE();  //     print(max lspher, 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("Offense
                                              //     against sine condition
                                              //     (coma): "))
  PRINT(ABERROSC, 5, 11);
  NEWLINE();  //     print(aberr osc, 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     (Maximum permissible): "))
  PRINT(MAXOSC, 5, 11);
  NEWLINE();  //     print(max osc, 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("Axial
                                              //     chromatic aberration: "))
  PRINT(ABERRLCHROM, 5, 11);
  NEWLINE();  //     print(aberr lchrom, 5, 11); newline
  /*ERROR: name_sym_idx is -1!*/ /*C_NAME*/;  //     print
                                              //     string(_imp_str_literal("
                                              //     (Maximum permissible): "))
  PRINT(MAXLCHROM, 5, 11);
  NEWLINE();  //     print(max lchrom, 5, 11); newline

  _imp_leave();
  exit(0);
  return (0);
}
// %end %of %program
