Compile-time calculation: Difference between revisions
Content added Content deleted
(OCaml: Add flambda compile-time reductions) |
(→{{header|6502 Assembly}}: Add implementation.) |
||
Line 57: | Line 57: | ||
+ L R1,=A(3628800) load reg with factorial |
+ L R1,=A(3628800) load reg with factorial |
||
</pre> |
</pre> |
||
=={{header|6502 Assembly}}== |
|||
{{works with|ca65 targeting the C-64}} |
|||
The ca65 cross-assembler supports computing and storing double-word (32-bit) integer values; unfortunately most 8-bit systems have no built-in support for manipulating such values. In this solution the assembler computes the actual value of 10! and stores it as a 32-bit integer; the runtime code converts that to floating point using ROM routines, dealing with the 16-bit halves of it one at a time. |
|||
<lang 6502>; Display the value of 10!, which is precomputed at assembly time |
|||
; |
|||
fac = $61 ; location of the floating point accumulator used by ROM routines |
|||
facsgn = fac+5 ; specific location of the sign byte |
|||
sys = $9e ; BASIC token for the SYS command to call our ML routine |
|||
start_of_basic = $0801 ; where our code is loaded |
|||
; ROM routines used |
|||
putfac = $aabc ; print out the value in the FAC |
|||
givayf = $b391 ; convert 16-bit integer in AY to floating-point value in FAC |
|||
fmult = $ba28 ; multiply FAC by float in memory |
|||
fadd = $b867 ; add float in memory to FAC |
|||
movfm = $bbd4 ; copy FAC to memory |
|||
; custom BASIC loader |
|||
.word start_of_basic |
|||
.org start_of_basic |
|||
.word last_line |
|||
.word * |
|||
.byte sys |
|||
.byte $30 + < (main/1000) |
|||
.byte $30 + <((main .mod 1000)/100) |
|||
.byte $30 + <((main .mod 100)/10) |
|||
.byte $30 + < (main .mod 10) |
|||
.byte 0 |
|||
last_line: |
|||
.word 0 |
|||
; 65536 as a float for multiplying the top half |
|||
fp65536: .byte 145,0,0,0,0,0 |
|||
; the actual value to print |
|||
tenfactorial: .dword 10*9*8*7*6*5*4*3*2*1 |
|||
; a place to stash partial results whlie using the FAC for other operations |
|||
fac_copy: .res 6 |
|||
main: |
|||
; convert the upper half |
|||
ldy tenfactorial+2 |
|||
lda tenfactorial+3 |
|||
jsr givayf |
|||
; and multiply by 65536 |
|||
lda #<fp65536 |
|||
ldy #>fp65536 |
|||
jsr fmult |
|||
; stash it |
|||
ldx #<fac_copy |
|||
ldy #>fac_copy |
|||
jsr movfm |
|||
; now convert the lower half |
|||
ldy tenfactorial |
|||
lda tenfactorial+1 |
|||
jsr givayf |
|||
; since it's the bottom half of a larger number |
|||
; it may have the high bit set, which will cause the above to |
|||
; treat it as negative. If that happened, correct by adding 65536. |
|||
lda facsgn |
|||
beq ok ; it's positive, so skip the correction |
|||
; it's negative, so add 65536 |
|||
lda #<fp65536 |
|||
ldy #>fp65536 |
|||
jsr fadd |
|||
ok: |
|||
; FAC now has lower half; add our copy of upper half |
|||
lda #<fac_copy |
|||
ldy #>fac_copy |
|||
jsr fadd |
|||
; and print out the result |
|||
jsr putfac |
|||
rts</lang> |
|||
{{Out}} |
|||
<pre> |
|||
**** COMMODORE 64 BASIC V2 **** |
|||
64K RAM SYSTEM 38911 BASIC BYTES FREE |
|||
READY. |
|||
LOAD"*",8,1 |
|||
SEARCHING FOR * |
|||
LOADING |
|||
READY. |
|||
RUN: |
|||
3628800 |
|||
READY.</pre> |
|||
=={{header|68000 Assembly}}== |
=={{header|68000 Assembly}}== |
||
VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants. |
VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants. |
||
Line 65: | Line 168: | ||
LEA tenfactorial,A1 ;load into A1 the memory address 10! = 0x375F00 |
LEA tenfactorial,A1 ;load into A1 the memory address 10! = 0x375F00 |
||
ADD.L #tenfactorial,D2 ;add 10! to whatever is stored in D2 and store the result in D2</lang> |
ADD.L #tenfactorial,D2 ;add 10! to whatever is stored in D2 and store the result in D2</lang> |
||
=={{header|Ada}}== |
=={{header|Ada}}== |