$set ans85 noosvs mf PROGRAM-ID. DIOPHANT. ****************************************************************** * * (C) Micro Focus Ltd. 1989 * * DIOPHANT.CBL * * DIOPHANTINE - solve linear equation Ax + By = C * for integers x and y. * * Method: * if A > B * swap A and B * fi * * when A = 0 * set x = 0, y = C/B as solution, and fail if non-integer * when A = 1 * set x = C, y = 0 as solution * otherwise * let D = largest integer < (B/A) * let E = largets integer < (C/A) * let F = B - A*D * let G = C - A*E * then Ax + By = C becomes * Ax + (F + A*D)y = (G + A*E) * so x + (F/A + D)y = (G/A + E) * and (F/A)y + v = G/A (since everything else is integral) * so solve * Fy + Av = G for integers y and v * * in COBOL terms: * * divide B by A giving D remainder F * divide C by A giving E remainder G * solve Av + Fw = G for integers v and w * set x = E - Dw + v, y = w as solution * * if swapped * swap x and y * fi * * ****************************************************************** WORKING-STORAGE SECTION. 01 InitA PIC s9(9) comp-5. 01 InitB PIC s9(9) comp-5. 01 InitC PIC s9(9) comp-5. 01 SolvX PIC s9(9) comp-5. 01 SolvY PIC s9(9) comp-5. 01 FailFg PIC X. 88 OK VALUE 'Y'. 88 BAD VALUE 'N'. 88 TRY VALUE '?'. LOCAL-STORAGE SECTION. 01 D PIC s9(9) comp-5. 01 E PIC s9(9) comp-5. 01 F PIC s9(9) comp-5. 01 G PIC s9(9) comp-5. 01 V PIC s9(9) comp-5. 01 TEMP PIC s9(9) comp-5. LINKAGE SECTION. 01 A PIC s9(9) comp-5. 01 B PIC s9(9) comp-5. 01 C PIC s9(9) comp-5. 01 X PIC s9(9) comp-5. 01 Y PIC s9(9) comp-5. PROCEDURE DIVISION. MAIN SECTION. DISPLAY "Solve Ax + By = C for integers x and y" DISPLAY "Enter value for A: " with no advancing ACCEPT InitA DISPLAY "Enter value for B: " with no advancing ACCEPT InitB DISPLAY "Enter value for C: " with no advancing ACCEPT InitC SET TRY TO TRUE CALL 'SOLVE' USING BY VALUE InitA InitB InitC BY REFERENCE SolvX SolvY IF OK DISPLAY "Solution is: x = " SolvX ", y = " SolvY ELSE DISPLAY "No Solution exists." END-IF STOP RUN. SOLVE-DIOPHANTINE SECTION. ENTRY 'SOLVE' USING BY VALUE A B C BY REFERENCE X Y. IF A > B * Use TEMP as a flag to indicate swapped or not. MOVE 1 TO TEMP CALL 'SWAP2' USING A B ELSE MOVE 0 TO TEMP END-IF EVALUATE A WHEN 0 DIVIDE C BY B GIVING D REMAINDER E IF E = 0 MOVE 0 TO X MOVE D TO Y SET OK TO TRUE ELSE * No solution exists. SET BAD TO TRUE MOVE 0 TO X, Y END-IF WHEN 1 MOVE C TO X MOVE 0 TO Y SET OK TO TRUE WHEN OTHER * We must delve deeper to find a solution. DIVIDE B BY A GIVING D REMAINDER F DIVIDE C BY A GIVING E REMAINDER G CALL 'SOLVE' USING BY VALUE A F G BY REFERENCE v Y COMPUTE X = E - ( D * Y ) + v END-EVALUATE IF TEMP = 1 CALL 'SWAP2' USING X Y END-IF EXIT PROGRAM. * Second level program to swap 2 variables using local temp variable. SWAPPER SECTION. ENTRY 'SWAP2' USING X Y. MOVE X TO TEMP MOVE Y TO X MOVE TEMP TO Y EXIT PROGRAM.