1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-01-09 13:33:26 +00:00

Floating point numbers

This commit is contained in:
David Schmenk 2024-07-12 22:25:32 -07:00
parent 257b31aa56
commit 2814843331

View File

@ -1,5 +1,7 @@
include "inc/cmdsys.plh"
include "inc/int32.plh"
include "inc/fpstr.plh"
include "inc/fpu.plh"
const TYPE_MASK = $70
const NIL = $00
@ -10,6 +12,7 @@ const SYM_TYPE = $20
const SYM_LEN = $0F
const NUM_TYPE = $30
const NUM_INT = $31
const NUM_FLOAT = $32
const MARK_BIT = $80
const MARK_MASK = $7F
@ -32,17 +35,24 @@ struc t_numint
res[t_elem]
word[2] intval
end
struc t_numfloat
res[t_elem]
res[t_fpureg] floatval
end
predef eval_expr(expr)
var sym_quote, sym_lambda, sym_cond
res[t_elem] pred_true = 0, 0, BOOL_TRUE
res[t_elem] pred_false = 0, 0, BOOL_FALSE
res[t_elem] pred_true = 0, 0, BOOL_TRUE
res[t_elem] pred_false = 0, 0, BOOL_FALSE
res[t_numint] nan = 0, 0, NUM_INT, 0, 0, 0, 128 // NaN
var cons_list = NULL
var cons_free = NULL
var int_list = NULL
var int_free = NULL
var float_list = NULL
var float_free = NULL
var sym_list = NULL
var assoc_list = NULL // SYM->value association list
@ -60,6 +70,7 @@ end
def mark_elems#0
mark_list(cons_list)
mark_list(int_list)
mark_list(float_list)
end
def sweep_expr(expr)#0
@ -114,8 +125,9 @@ def collect_list(listhead, freehead)#2
end
def collect_unused#0
cons_list, cons_free = collect_list(cons_list, cons_free)
int_list, int_free = collect_list(int_list, int_free)
cons_list, cons_free = collect_list(cons_list, cons_free)
int_list, int_free = collect_list(int_list, int_free)
float_list, float_free = collect_list(float_list, float_free)
end
export def gc#0
@ -177,6 +189,43 @@ export def new_int(intlo, inthi)#1
return intptr
end
def match_float(extptr)
var floatptr
byte i
floatptr = float_list
while floatptr
for i = 0 to 4
if floatptr=>floatval[i] <> extptr=>[i]
break
fin
next
if i > 4
return floatptr
fin
floatptr = floatptr=>link
loop
return NULL
end
export def new_float(extptr)#1
var floatptr
floatptr = match_float(extptr)
if floatptr; return floatptr; fin
if float_free
floatptr = float_free
float_free = float_free=>link
else
floatptr = heapalloc(t_numfloat)
fin
floatptr=>link = float_list
float_list = floatptr
floatptr->type = NUM_FLOAT
memcpy(floatptr + floatval, extptr, t_fpureg)
return floatptr
end
def match_sym(symstr)
var symptr
byte len, typelen, i
@ -293,6 +342,9 @@ def print_atom(atom)#0
is NUM_INT
puti32(atom + intval)
break
is NUM_FLOAT
puts(ext2str(atom + floatval, @prstr, 6, 4, FPSTR_FIXED|FPSTR_STRIP|FPSTR_FLEX))
break
wend
break
is SYM_TYPE
@ -336,26 +388,51 @@ end
// Parse textual representation of S-expression
//
def is_int(c); return c >= '0' and c <= '9'; end
def is_num(c); return c >= '0' and c <= '9'; end
def is_alphasym(c)
return (c >= '*' and c <= 'z') and (c <> '.') and (c <> ',')
end
def parse_int(evalptr)#2 // return evalptr, intptr
var int[2]
def parse_num(evalptr)#2 // return evalptr, intptr
var startptr
var int[2], ext[5]
byte sign
zero32
sign = FALSE
if ^evalptr == '-'
sign = TRUE
evalptr++
fin
startptr = evalptr
while ^evalptr >= '0' and ^evalptr <= '9'
muli16(10); addi16(^evalptr - '0')
evalptr++
loop
if (evalptr - startptr > 10) or ^evalptr == '.' or toupper(^evalptr) == 'E'
if ^evalptr == '.'
evalptr++
while ^evalptr >= '0' and ^evalptr <= '9'
evalptr++
loop
fin
if toupper(^evalptr) == 'E'
^evalptr = 'E'
evalptr++
if ^evalptr == '-' or ^evalptr == '+'; evalptr++; fin
while ^evalptr >= '0' and ^evalptr <= '9'
evalptr++
loop
fin
if sign; startptr--; fin
^(startptr - 1) = evalptr - startptr
str2ext(startptr - 1, @ext)
return evalptr, new_float(@ext)
fin
zero32
while startptr <> evalptr
muli16(10); addi16(^startptr - '0')
startptr++
loop
if sign; neg32; fin
store32(@int)
return evalptr, new_int(int[0], int[1])
@ -435,8 +512,8 @@ export def parse_expr(evalptr, level, refill)#2 // return evalptr, exprptr
elemptr = NULL
break
otherwise
if is_int(^evalptr) or (^evalptr == '-' and is_int(^(evalptr+1)))
evalptr, elemptr = parse_int(evalptr)
if is_num(^evalptr) or (^evalptr == '-' and is_num(^(evalptr+1)))
evalptr, elemptr = parse_num(evalptr)
elsif is_alphasym(^evalptr)
evalptr, elemptr = parse_sym(evalptr)
else
@ -677,101 +754,228 @@ def natv_setq(expr)
return valptr
end
export def eval_num(expr)#2
export def eval_num(expr)
var result
result = eval_expr(expr=>car)
if result->type == NUM_INT
return result=>intval[0], result=>intval[1]
if result and (result->type & TYPE_MASK == NUM_TYPE)
return result
fin
puts("Not an number\n")
return 0, 0
return @nan
end
def push_int32(intptr)#0
var[2] int
byte isneg
isneg = FALSE
if intptr=>[1] < 0
load32(intptr)
isneg = TRUE
neg32
store32(@int)
else
int[0] = intptr=>[0]
int[1] = intptr=>[1]
fin
fpu:pushInt(@int[1])
fpu:scalebXInt(16)
fpu:pushInt(@int[0])
fpu:addXY()
if isneg
fpu:negX()
fin
end
def push_num(numptr)#0
var int
if numptr->type == NUM_FLOAT
fpu:pushExt(numptr + floatval)
elsif numptr->type == NUM_INT
push_int32(numptr + intval)
else
puts("Pushing non number!\n")
int = 0
fpu:pushInt(@int)
fin
end
def natv_add(expr)
var[2] sum, num
var num
var[2] intsum
var[5] extsum
sum[0] = 0
sum[1] = 0
while expr
num[0], num[1] = eval_num(expr)
load32(@num)
add32(@sum)
store32(@sum)
expr = expr=>cdr
loop
return new_int(sum[0], sum[1])
intsum[0] = 0
intsum[1] = 0
num = eval_num(expr)
expr = expr=>cdr
if num->type == NUM_INT
//
// Sum as integers unless a float is encountered
//
intsum[0] = num=>intval[0]
intsum[1] = num=>intval[1]
while expr
num = eval_num(expr)
expr = expr=>cdr
if num->type == NUM_FLOAT
break
fin
load32(@intsum)
add32(num + intval)
store32(@intsum)
loop
fin
if num->type == NUM_FLOAT
//
// Sum as floating point numbers
//
push_int32(@intsum)
push_num(num)
fpu:addXY()
while expr
num = eval_num(expr)
push_num(num)
fpu:addXY()
expr = expr=>cdr
loop
fpu:pullExt(@extsum)
return new_float(@extsum)
fin
return new_int(intsum[0], intsum[1])
end
def natv_sub(expr)
var[2] dif, num
var num1, num2
var[2] dif
var[5] ext
num[0], num[1] = eval_num(expr)
dif[0], dif[1] = eval_num(expr=>cdr)
load32(@num)
sub32(@dif)
store32(@dif)
return new_int(dif[0], dif[1])
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
sub32(num2 + intval)
store32(@dif)
return new_int(dif[0], dif[1])
fin
push_num(num1)
push_num(num2)
fpu:subXY()
fpu:pullExt(@ext)
return new_float(@ext)
end
def natv_mul(expr)
var[2] mul, num
var num1, num2
var[2] mul
var[5] ext
num[0], num[1] = eval_num(expr)
mul[0], mul[1] = eval_num(expr=>cdr)
load32(@num)
mul32(@mul)
store32(@mul)
return new_int(mul[0], mul[1])
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
mul32(num2 + intval)
store32(@mul)
return new_int(mul[0], mul[1])
fin
push_num(num1)
push_num(num2)
fpu:mulXY()
fpu:pullExt(@ext)
return new_float(@ext)
end
def natv_div(expr)
var[2] num, div
var num1, num2
var[2] div
var[5] ext
num[0], num[1] = eval_num(expr)
div[0], div[1] = eval_num(expr=>cdr)
load32(@num)
div32(@div)
store32(@div)
return new_int(div[0], div[1])
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
div32(num2 + intval)
store32(@div)
return new_int(div[0], div[1])
fin
push_num(num1)
push_num(num2)
fpu:divXY()
fpu:pullExt(@ext)
return new_float(@ext)
end
def natv_rem(expr)
var[2] num, div
var num1, num2
var[2] rem, div
var[5] ext
num[0], num[1] = eval_num(expr)
div[0], div[1] = eval_num(expr=>cdr)
load32(@num)
num[1], num[0] = div32(@div)
return new_int(num[0], num[1])
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
rem[1], rem[0] = div32(num2 + intval)
return new_int(rem[0], rem[1])
fin
push_num(num1)
push_num(num2)
fpu:remXY()
fpu:pullExt(@ext)
return new_float(@ext)
end
def natv_neg(expr)
var num[2]
var num
var[2] neg
var[5] ext
num[0], num[1] = eval_num(expr)
load32(@num)
neg32
store32(@num)
return new_int(num[0], num[1])
num = eval_num(expr)
if num=>type == NUM_INT
load32(num + intval)
neg32
store32(@neg)
return new_int(neg[0], neg[1])
fin
push_num(num)
fpu:negX()
fpu:pullExt(@ext)
return new_float(@ext)
end
def natv_gt(expr)
var[2] num1, num2
var num1, num2
var[5] ext
num1[0], num1[1] = eval_num(expr)
num2[0], num2[1] = eval_num(expr=>cdr)
load32(@num1)
return bool_pred(isgt32(@num2))
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
return bool_pred(isgt32(num2 + intval))
fin
push_num(num2)
push_num(num1)
fpu:subXY()
fpu:pullExt(@ext)
return bool_pred(ext[4] < 0)
end
def natv_lt(expr)
var[2] num1, NUM2
var num1, num2
var[5] ext
num1[0], num1[1] = eval_num(expr)
num2[0], num2[1] = eval_num(expr=>cdr)
load32(@num1)
return bool_pred(islt32(@num2))
num1 = eval_num(expr)
num2 = eval_num(expr=>cdr)
if num1->type == NUM_INT and num2->type == NUM_INT
load32(num1 + intval)
return bool_pred(islt32(num2 + intval))
fin
push_num(num1)
push_num(num2)
fpu:subXY()
fpu:pullExt(@ext)
return bool_pred(ext[4] < 0)
end
def natv_print(expr)
@ -814,5 +1018,6 @@ new_sym("NEG")=>natv = @natv_neg
new_sym(">")=>natv = @natv_gt
new_sym("<")=>natv = @natv_lt
new_sym("PRINT")=>natv = @natv_print
fpu:reset()
return modkeep | modinitkeep
done