dos_compilers/Microsoft COBOL v45/DEMO/DIOPHANT.CBL
2024-07-24 07:18:17 -07:00

144 lines
4.7 KiB
COBOL

$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.