Sylvester's sequence: Difference between revisions

Added PL/M
(→‎{{header|ALGOL 68}}: Corrected spelling of reciprocal - thanks to Gerard Schildberger for showing me the error of my ways...)
(Added PL/M)
Line 277:
10: 165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
sum of reciprocals: 0.999999999999999999...99999999999999999635 (213 digits)
</pre>
 
=={{header|PL/M}}==
As the original 8080 PL/M only has unsigned 8 and 16 bit items, this Uses code from the PL/M [[Long Multiplication]] sample routines.
<br>It doesn't calculate the reciprocal sum as 8080 PL/M has no floating point...
<br>This sample can be compiled with the original 8080 PL/M compiler and run under CP/M (or an emulator or clone).
<lang plm>100H: /* CALCULATE ELEMENTS OF SYLVESTOR'S SEQUENCE */
 
BDOS: PROCEDURE( FN, ARG ); /* CP/M BDOS SYSTEM CALL */
DECLARE FN BYTE, ARG ADDRESS;
GOTO 5;
END BDOS;
PRINT$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PRINT$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
DECLARE PRINT$NL LITERALLY 'PRINT$STRING( .( 0DH, 0AH, ''$'' ) )';
 
DECLARE LONG$INTEGER LITERALLY '(201)BYTE';
DECLARE DIGIT$BASE LITERALLY '10';
 
/* PRINTS A LONG INTEGER */
PRINT$LONG$INTEGER: PROCEDURE( N$PTR );
DECLARE N$PTR ADDRESS;
DECLARE N BASED N$PTR LONG$INTEGER;
DECLARE ( D, F ) BYTE;
F = N( 0 );
DO D = 1 TO N( 0 );
CALL PRINT$CHAR( N( F ) + '0' );
F = F - 1;
END;
END PRINT$LONG$INTEGER;
/* IMPLEMENTS LONG MULTIPLICATION, C IS SET TO A * B */
/* C CAN BE THE SAME LONG$INTEGER AS A OR B */
LONG$MULTIPLY: PROCEDURE( A$PTR, B$PTR, C$PTR );
DECLARE ( A$PTR, B$PTR, C$PTR ) ADDRESS;
DECLARE ( A BASED A$PTR, B BASED B$PTR, C BASED C$PTR ) LONG$INTEGER;
DECLARE MRESULT LONG$INTEGER;
DECLARE RPOS BYTE;
 
/* MULTIPLIES THE LONG INTEGER IN B BY THE INTEGER A, THE RESULT */
/* IS ADDED TO C, STARTING FROM DIGIT START */
/* OVERFLOW IS IGNORED */
MULTIPLY$ELEMENT: PROCEDURE( A, B$PTR, C$PTR, START );
DECLARE ( B$PTR, C$PTR ) ADDRESS;
DECLARE ( A, START ) BYTE;
DECLARE ( B BASED B$PTR, C BASED C$PTR ) LONG$INTEGER;
DECLARE ( CDIGIT, D$CARRY, BPOS, CPOS ) BYTE;
D$CARRY = 0;
CPOS = START;
DO BPOS = 1 TO B( 0 );
CDIGIT = C( CPOS ) + ( A * B( BPOS ) ) + D$CARRY;
IF CDIGIT < DIGIT$BASE THEN D$CARRY = 0;
ELSE DO;
/* HAVE DIGITS TO CARRY */
D$CARRY = CDIGIT / DIGIT$BASE;
CDIGIT = CDIGIT MOD DIGIT$BASE;
END;
C( CPOS ) = CDIGIT;
CPOS = CPOS + 1;
END;
C( CPOS ) = D$CARRY;
/* REMOVE LEADING ZEROS BUT IF THE NUMBER IS 0, KEEP THE FINAL 0 */
DO WHILE( CPOS > 1 AND C( CPOS ) = 0 );
CPOS = CPOS - 1;
END;
C( 0 ) = CPOS;
END MULTIPLY$ELEMENT ;
 
/* THE RESULT WILL BE COMPUTED IN MRESULT, ALLOWING A OR B TO BE C */
DO RPOS = 1 TO LAST( MRESULT ); MRESULT( RPOS ) = 0; END;
/* MULTIPLY BY EACH DIGIT AND ADD TO THE RESULT */
DO RPOS = 1 TO A( 0 );
IF A( RPOS ) <> 0 THEN DO;
CALL MULTIPLY$ELEMENT( A( RPOS ), B$PTR, .MRESULT, RPOS );
END;
END;
/* RETURN THE RESULT IN C */
DO RPOS = 0 TO MRESULT( 0 ); C( RPOS ) = MRESULT( RPOS ); END;
END;
/* ADDS THE INTEGER A TO THE LONG$INTEGER N */
ADD$BYTE$TO$LONG$INTEGER: PROCEDURE( A, N$PTR );
DECLARE A BYTE, N$PTR ADDRESS;
DECLARE N BASED N$PTR LONG$INTEGER;
DECLARE ( D, D$CARRY, DIGIT ) BYTE;
D = 1;
D$CARRY = A;
DO WHILE( D$CARRY > 0 );
DIGIT = N( D ) + D$CARRY;
IF DIGIT < DIGIT$BASE THEN DO;
N( D ) = DIGIT;
D$CARRY = 0;
END;
ELSE DO;
D$CARRY = DIGIT / DIGIT$BASE;
N( D ) = DIGIT MOD DIGIT$BASE;
D = D + 1;
IF D > N( 0 ) THEN DO;
/* THE NUMBER NOW HAS AN EXTRA DIGIT */
N( 0 ) = D;
N( D ) = D$CARRY;
D$CARRY = 0;
END;
END;
END;
END ADD$BYTE$TO$LONG$INTEGER;
/* FIND THE FIRST 10 ELEMENTS OF SYLVESTOR'S SEQUENCE */
DECLARE ( SEQ$ELEMENT, PRODUCT ) LONG$INTEGER;
DECLARE ( I, D ) BYTE;
DO D = 2 TO LAST( PRODUCT ); PRODUCT( D ) = 0; END;
DO D = 2 TO LAST( SEQ$ELEMENT ); SEQ$ELEMENT( D ) = 0; END;
SEQ$ELEMENT( 0 ) = 1; /* THE FIRST SEQUENCE ELEMENT HAS 1 DIGIT... */
SEQ$ELEMENT( 1 ) = 2; /* WHICH IS 2 */
PRODUCT( 0 ) = 1;
PRODUCT( 1 ) = 2;
CALL PRINT$LONG$INTEGER( .SEQ$ELEMENT ); /* SHOW ELEMENT 1 */
CALL PRINT$NL;
DO I = 2 TO 9;
DO D = 0 TO PRODUCT( 0 ); SEQ$ELEMENT( D ) = PRODUCT( D ); END;
CALL ADD$BYTE$TO$LONG$INTEGER( 1, .SEQ$ELEMENT );
CALL PRINT$LONG$INTEGER( .SEQ$ELEMENT );
CALL LONG$MULTIPLY( .SEQ$ELEMENT, .PRODUCT, .PRODUCT );
CALL PRINT$NL;
END;
/* THE FINAL ELEMENT IS THE PRODUCT PLUS 1 */
CALL ADD$BYTE$TO$LONG$INTEGER( 1, .PRODUCT );
CALL PRINT$LONG$INTEGER( .PRODUCT );
CALL PRINT$NL;
EOF</lang>
{{out}}
<pre>
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
</pre>
 
3,068

edits