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}}==