mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-23 22:30:51 +00:00
Implement FX2DEC. Not perfect, but good enough I think.
This commit is contained in:
parent
2a62ad32d2
commit
56fb5d9743
@ -5,7 +5,8 @@ MAKEFLAGS += --no-builtin-rules
|
||||
.SUFFIXES:
|
||||
.SECONDARY:
|
||||
|
||||
MPW ?= mpw
|
||||
MPWFLAGS = -DMPWVersion=3.2
|
||||
MPW ?= mpw
|
||||
|
||||
LIBS = \
|
||||
{Libraries}Stubs.o \
|
||||
@ -25,7 +26,7 @@ LDFLAGS = -w -c 'MPS ' -t MPST \
|
||||
SCFLAGS = -p
|
||||
|
||||
TARGETS = test_new_handle test_new_handle_2 test_new_pointer test_volumes \
|
||||
test_createresfile test_hwpriv
|
||||
test_createresfile test_hwpriv test_sane
|
||||
|
||||
all : $(TARGETS)
|
||||
|
||||
@ -44,10 +45,16 @@ clean :
|
||||
# test_volumes : o/test_volumes.o
|
||||
# mpw Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
test_sane: o/nan.o o/test_sane.o
|
||||
$(MPW) $(MPWFLAGS) Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
% : o/%.o
|
||||
$(MPW) Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(MPW) $(MPWFLAGS) Link $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
o/%.o : %.c
|
||||
$(MPW) SC $(SCFLAGS) $< -o $@
|
||||
$(MPW) $(MPWFLAGS) SC $(SCFLAGS) $< -o $@
|
||||
|
||||
o/%.o : %.asm
|
||||
$(MPW) $(MPWFLAGS) Asm $(ASMFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
35
test/nan.asm
Normal file
35
test/nan.asm
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
case on
|
||||
|
||||
export nan, __inf, inf
|
||||
|
||||
nan proc
|
||||
; The MPW 3.2 version of nan is broken. This what it's supposed to do.
|
||||
; extended (80-bit) returns via d0, d1, a0
|
||||
|
||||
MOVEM.L data,D0/D1/A0
|
||||
MOVE.W #$4000,D1
|
||||
MOVE.B $0004(A7),D1
|
||||
BNE.S swap
|
||||
MOVE.B #$15,D1
|
||||
swap
|
||||
SWAP D1
|
||||
RTS
|
||||
|
||||
entry inf
|
||||
entry __inf
|
||||
|
||||
inf
|
||||
__inf
|
||||
|
||||
MOVEM.L data,D0/D1/A0
|
||||
RTS
|
||||
|
||||
data
|
||||
dc.l $00007fff
|
||||
dc.l $00000000
|
||||
dc.l $00000000
|
||||
|
||||
end
|
||||
endp
|
||||
|
229
test/test_sane.c
Normal file
229
test/test_sane.c
Normal file
@ -0,0 +1,229 @@
|
||||
#include <Math.h>
|
||||
#include <SANE.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//extern pascal extended NAN(short x);
|
||||
|
||||
void dump_decimal(const decimal *d)
|
||||
{
|
||||
fprintf(stdout, "%d : %d : %.*s\n",
|
||||
d->sgn, d->exp, d->sig.length, d->sig.text);
|
||||
}
|
||||
|
||||
|
||||
void test_fxc2dec(void)
|
||||
{
|
||||
decimal d;
|
||||
decform df;
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 100;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : -18 : 1125000000000000000
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : -9 : 1125000000
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 2;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : -1 : 11
|
||||
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 100;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : -18 : 1125000000000000000
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : -10 : 11250000000
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 2;
|
||||
num2dec(&df, 1.125, &d);
|
||||
dump_decimal(&d);
|
||||
//0 : -2 : 112
|
||||
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 100;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : 7 : 1000000000000000000
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : 16 : 1000000000
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 2;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : 24 : 10
|
||||
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 100;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : 7 : 1000000000000000000
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
// 0 : 7 : 1000000000000000000
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 2;
|
||||
num2dec(&df, 1e25, &d);
|
||||
dump_decimal(&d);
|
||||
//0 : 7 : 1000000000000000000
|
||||
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 0, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 0, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 0;
|
||||
num2dec(&df, -0.0, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 0;
|
||||
num2dec(&df, -0.0, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 0;
|
||||
num2dec(&df,nan(1), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 0;
|
||||
num2dec(&df, nan(2), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df,-nan(3), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, nan(4), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df,-inf(), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, -inf(), &d);
|
||||
dump_decimal(&d);
|
||||
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 0;
|
||||
num2dec(&df, inf(), &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 0;
|
||||
num2dec(&df, inf(), &d);
|
||||
dump_decimal(&d);
|
||||
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 0.125, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 10;
|
||||
num2dec(&df, 0.125, &d);
|
||||
dump_decimal(&d);
|
||||
//
|
||||
|
||||
df.style = 0;
|
||||
df.digits = 4;
|
||||
num2dec(&df, 0.00000125, &d);
|
||||
dump_decimal(&d);
|
||||
// s/b -9 1250
|
||||
|
||||
df.style = 1;
|
||||
df.digits = 4;
|
||||
num2dec(&df, 0.00000125, &d);
|
||||
dump_decimal(&d);
|
||||
// s/b -4 0
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
extended x;
|
||||
decimal d;
|
||||
|
||||
short index;
|
||||
short valid;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
index = 0;
|
||||
valid = 0;
|
||||
str2dec("1.125", &index, &d, &valid);
|
||||
x = dec2num(&d);
|
||||
|
||||
|
||||
|
||||
test_fxc2dec();
|
||||
|
||||
return 0;
|
||||
}
|
171
toolbox/sane.cpp
171
toolbox/sane.cpp
@ -35,6 +35,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "stackframe.h"
|
||||
@ -50,6 +51,7 @@ namespace SANE
|
||||
using std::to_string;
|
||||
using std::fpclassify;
|
||||
using std::signbit;
|
||||
using std::abs;
|
||||
|
||||
using its_complicated::to_string;
|
||||
using its_complicated::fpclassify;
|
||||
@ -310,6 +312,72 @@ using its_complicated::signbit;
|
||||
ToolBox::WritePString(address + _sig, sig);
|
||||
}
|
||||
|
||||
void format_f(extended x, int precision, std::string &mm, std::string &nn)
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
|
||||
mm.clear();
|
||||
nn.clear();
|
||||
|
||||
if (precision < 0) precision = 0;
|
||||
int length = asprintf(&buffer, "%.*Lf", precision, x);
|
||||
std::string tmp(buffer, length);
|
||||
free(buffer);
|
||||
|
||||
auto dot = tmp.find('.');
|
||||
if (dot == tmp.npos)
|
||||
{
|
||||
mm = std::move(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mm = tmp.substr(0, dot);
|
||||
nn = tmp.substr(dot + 1);
|
||||
}
|
||||
|
||||
// skip mm if it's 0
|
||||
if (mm.length() == 1 && mm.front() == '0') mm.clear();
|
||||
|
||||
// skip nn if it's 0000...
|
||||
if (std::all_of(nn.begin(), nn.end(), [](char c){ return c == '0'; }))
|
||||
nn.clear();
|
||||
}
|
||||
|
||||
void format_e(extended x, int precision, std::string &mm, std::string &nn, int &exp)
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
|
||||
exp = 0;
|
||||
mm.clear();
|
||||
nn.clear();
|
||||
|
||||
if (precision < 0) precision = 0;
|
||||
if (precision > 19) precision = 19;
|
||||
|
||||
int length = asprintf(&buffer, "%.*Le", precision, x);
|
||||
// output mm . nn e[+-]exp
|
||||
// mm e[+-]exp
|
||||
std::string tmp(buffer, length);
|
||||
free(buffer);
|
||||
|
||||
auto dot = tmp.find('.');
|
||||
auto e = tmp.find('e');
|
||||
|
||||
if (dot == tmp.npos)
|
||||
{
|
||||
mm = tmp.substr(0, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
mm = tmp.substr(0, dot);
|
||||
nn = tmp.substr(dot + 1, e - dot - 1);
|
||||
}
|
||||
|
||||
char sign = tmp[e+1];
|
||||
tmp = tmp.substr(e + 2);
|
||||
exp = std::stoi(tmp);
|
||||
if (sign == '-') exp = -exp;
|
||||
}
|
||||
|
||||
uint16_t fx2dec()
|
||||
{
|
||||
@ -331,8 +399,6 @@ using its_complicated::signbit;
|
||||
|
||||
Log(" FX2DEC(%08x, %08x, %08x, %04x)\n", f_adr, a_adr, d_adr, op);
|
||||
|
||||
fprintf(stderr, "warning: FX2DEC not yet implemented\n");
|
||||
|
||||
extended s = readnum<extended>(a_adr);
|
||||
df = decform::read(f_adr);
|
||||
|
||||
@ -353,18 +419,20 @@ using its_complicated::signbit;
|
||||
* [-]mmm[.nnn]
|
||||
*/
|
||||
|
||||
// this doesn't entirely apply for fx2dec, though.
|
||||
|
||||
if (df.digits < 0) df.digits = 0;
|
||||
if (df.digits > 19) df.digits = 19;
|
||||
|
||||
fpinfo fpi(s);
|
||||
//fprintf(stderr, "%02x %02x %08x %016llx\n", fpi.sign, fpi.one, fpi.exp, fpi.sig);
|
||||
//fprintf(stderr, "%02x %02x %d %016llx\n", fpi.sign, fpi.one, fpi.exp, fpi.sig);
|
||||
|
||||
|
||||
d.sgn = signbit(s);
|
||||
|
||||
// handle infinity, nan as a special case.
|
||||
switch (fpclassify(s))
|
||||
{
|
||||
case FP_ZERO:
|
||||
d.sgn = signbit(s);
|
||||
d.sig = "0";
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
@ -374,7 +442,6 @@ using its_complicated::signbit;
|
||||
{
|
||||
char buffer[20]; // 16 + 2 needed
|
||||
snprintf(buffer, 20, "N%016llx", fpi.sig);
|
||||
d.sgn = signbit(s);
|
||||
d.sig = buffer;
|
||||
d.write(d_adr);
|
||||
}
|
||||
@ -382,7 +449,6 @@ using its_complicated::signbit;
|
||||
|
||||
case FP_INFINITE:
|
||||
|
||||
d.sgn = signbit(s);
|
||||
d.sig = "I";
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
@ -394,20 +460,95 @@ using its_complicated::signbit;
|
||||
|
||||
// normal and subnormal handled here....
|
||||
|
||||
#if 0
|
||||
if (df.style == decform::FIXEDDECIMAL)
|
||||
// float decimal: df.digits refers to the total length
|
||||
// fixed decimal: df.digits refers to the fractional part only.
|
||||
|
||||
s = abs(s);
|
||||
|
||||
|
||||
if (s < 1.0 && df.style == decform::FLOATDECIMAL)
|
||||
{
|
||||
char buffer[decimal::SIGDIGLEN];
|
||||
snprintf(buffer, sizeof(buffer), "%.*Lg", df.digits, s);
|
||||
std::string mm;
|
||||
std::string nn;
|
||||
|
||||
format_e(s, df.digits - 1, mm, nn, d.exp);
|
||||
|
||||
d.sig = mm + nn;
|
||||
|
||||
// better be < 0...
|
||||
if (d.exp < 0)
|
||||
d.exp -= nn.length();
|
||||
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
else // s > 1
|
||||
{
|
||||
|
||||
// ugh, really don't want to write this code right now.
|
||||
std::string mm;
|
||||
std::string nn;
|
||||
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
format_f(s, df.digits, mm, nn);
|
||||
|
||||
if (mm.empty() && nn.empty())
|
||||
{
|
||||
// very large 0.
|
||||
d.sig = "0";
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if nn is empty (or 0s), this is a large number,
|
||||
// and we don't have to worry about the fraction.
|
||||
if (nn.empty())
|
||||
{
|
||||
d.exp = 0;
|
||||
|
||||
if (df.style == decform::FIXEDDECIMAL) df.digits = 19;
|
||||
|
||||
// limit the length.
|
||||
if (mm.length() > df.digits)
|
||||
{
|
||||
d.exp = mm.length() - df.digits;
|
||||
mm.resize(df.digits);
|
||||
}
|
||||
d.sig = std::move(mm);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (df.style == decform::FIXEDDECIMAL)
|
||||
{
|
||||
// digits is the total size, mm + nn
|
||||
// re-format with new precision.
|
||||
// this is getting repetitive...
|
||||
|
||||
if (mm.length())
|
||||
{
|
||||
int precision = df.digits - mm.length();
|
||||
if (precision < 0) precision = 1;
|
||||
|
||||
format_f(s, precision, mm, nn);
|
||||
}
|
||||
}
|
||||
// todo -- if mm is empty and nn has leading 0s,
|
||||
// drop the leading 0s and adjust the exponent
|
||||
// accordingly.
|
||||
|
||||
d.sig = mm + nn;
|
||||
d.exp = -nn.length();
|
||||
|
||||
if (d.sig.length() > 19)
|
||||
{
|
||||
d.exp += (d.sig.length() - 19);
|
||||
d.sig.resize(19);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
d.write(d_adr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user