Skip to content

Commit 46073e4

Browse files
committed
Octave, bc, and gnuplot scripts supporting math dev
This is a collection of scripts that are useful in developing math approximations. Refs: gh-206 Signed-off-by: Matthias Kretz <[email protected]>
1 parent e2f5351 commit 46073e4

16 files changed

+344
-0
lines changed

math/cosf.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function y = cosf (x)
2+
x2 = x.*x;
3+
y = 0;
4+
y = y .* x2 + to_float(0x573F9F, -45);
5+
y = y .* x2 - to_float(0x49CBA5, -37);
6+
y = y .* x2 + to_float(0x0F76C7, -29);
7+
y = y .* x2 - to_float(0x13F27E, -22);
8+
y = y .* x2 + to_float(0x500D01, -16);
9+
y = y .* x2 - to_float(0x360B61, -10);
10+
y = y .* x2 + to_float(0x2AAAAB, -5);
11+
y = y .* (x2 .* x2) - .5 * x2 + 1.;
12+
endfunction

math/floattool

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/bin/zsh
2+
3+
function usage() {
4+
cat <<EOF
5+
Usage: $0 [options] <input number>
6+
7+
This tool splits an arbitrary number into IEEE 768 floats.
8+
Options:
9+
--help|-h this message
10+
-m <bits> mantissa bits, 23 for sp and 52 for dp (default 23)
11+
-n <count> number of constants to split the input into (default 2)
12+
-z <bits> number of trailing zero bits in the first count-1 constants (default 12)
13+
-p only output positive numbers (or rather numbers with the same sign as the input number)
14+
-o <offset> add this offset to the mantissa of the first value
15+
-f <function> use the argument as output function name for easier cut and paste (default depends on -m)
16+
17+
Available functions:
18+
fak(x) : factorial of x
19+
floor(x)
20+
round(x)
21+
log2(x)
22+
abs(x)
23+
sign(x)
24+
exponent(x)
25+
l(x)
26+
s(x)
27+
c(x)
28+
29+
EOF
30+
}
31+
32+
bits=23
33+
count=2
34+
zerobits=12
35+
mantissaReduction=round
36+
offset=0
37+
const_fun=
38+
39+
while (( $# > 0 )); do
40+
case "$1" in
41+
--help|-h) usage; exit ;;
42+
-m) bits=$2; shift ;;
43+
-m*) bits=${1#-m} ;;
44+
-n) count=$2; shift ;;
45+
-n*) count=${1#-n} ;;
46+
-z) zerobits=$2; shift ;;
47+
-z*) zerobits=${1#-z} ;;
48+
-o) offset=$2; shift ;;
49+
-o*) offset=${1#-o} ;;
50+
-f) const_fun=$2; shift ;;
51+
-f*) const_fun=${1#-o} ;;
52+
-p) mantissaReduction=floor ;;
53+
*) input="$input $1" ;;
54+
esac
55+
shift
56+
done
57+
58+
if (($bits == 23)) && [[ -z "$const_fun" ]]; then
59+
const_fun="const auto c## = Vc::Detail::floatConstant"
60+
elif [[ -z "$const_fun" ]]; then
61+
const_fun="const auto c## = Vc::Detail::doubleConstant"
62+
fi
63+
64+
BC_LINE_LENGTH=0 bc -l <<EOF
65+
scale=400
66+
pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936073
67+
oneoverlog2=1/l(2)
68+
scale=100
69+
define fak(x) { r=x; while(x>1) { r *= --x; }; return r; }
70+
define floor(x) { tmp=scale; scale=0; n = x/1; scale=tmp; return n; }
71+
define round(x) { return floor(x + 0.5); }
72+
define log2(x) { return l(x)*oneoverlog2; }
73+
define abs(x) { if(x < 0) return -x; return x; }
74+
define sign(x) { tmp=scale; scale=0; n = x/abs(x); scale=tmp; return n; }
75+
define exponent(x) { x = abs(x); e = floor(log2(x)); while(x*2^-e < 1) e -= 1; while(x*2^-e >= 2) e += 1; return e; }
76+
define setprecision(x, p) { return round(x * 2^(p-exponent(x))) * 2^(exponent(x)-p); }
77+
define float(x) { return setprecision(x,${bits}); }
78+
define void printfloat(s,m,e) {
79+
print "${const_fun}<", s, ", 0x"
80+
obase=16
81+
print m
82+
obase=10
83+
print ", ", e, ">(); // ", s*(m*2^(e-${bits})+2^e), "\n"
84+
}
85+
86+
/* unused, but can be used to print full binary representation of floats */
87+
define void printfloat_int(x) {
88+
h=0
89+
if (x < 0) {
90+
h = 2^31
91+
x = -x;
92+
}
93+
e=exponent(x)
94+
h+=${mantissaReduction}(x*2^(${bits}-e)-2^${bits})
95+
h+=(e+127)*2^23
96+
obase=16
97+
print "0x", h
98+
obase=10
99+
}
100+
101+
in=${input}
102+
print "// ", in, "\n"
103+
x=in
104+
shift1=${bits}-${zerobits}
105+
shift2=${bits}-shift1
106+
for(i = 1; i < ${count}; ++i) {
107+
s=sign(x)
108+
x=abs(x)
109+
e=exponent(x)
110+
m=(${mantissaReduction}(x*2^(shift1-e)-2^shift1) + ${offset})*(2^shift2)
111+
printfloat(s,m,e)
112+
x=s*(x-(m*(2^-${bits})+1)*(2^e))
113+
if(x == 0) {
114+
break
115+
}
116+
}
117+
if(x == 0) {
118+
print "no remainder.\n"
119+
} else {
120+
s=sign(x)
121+
x=abs(x)
122+
e=exponent(x)
123+
m=${mantissaReduction}(x*2^(${bits}-e)-2^${bits})
124+
printfloat(s,m,e)
125+
x=s*(x-(m*(2^-${bits})+1)*(2^e))
126+
if(x == 0) {
127+
print "no remainder.\n"
128+
} else {
129+
err=abs(x/in)
130+
e=floor(l(err)/l(10))-1
131+
ulp=x * 2^(23 - exponent(in))
132+
scale=1
133+
print "relative error: ", (err*10^-e)/1, "e", e, "\n"
134+
print (ulp*1000+0.5)/1*0.001, " ulp\n"
135+
}
136+
}
137+
EOF
138+
139+
# vim: sw=2 et

math/fold_pi4_single.m

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function x = fold_pi4_single(x)
2+
x = round_to_float(x);
3+
expected = round_to_float(x - floor(x / (pi/2) + .5)*(pi/2));
4+
y = round_to_float(floor(x * round_to_float(2/pi) + .5)) * 2;
5+
printf("y = %i = %s\n", y, hexfloat(y));
6+
while(y > 0)
7+
p2 = 2^floor(log2(y));
8+
y -= p2;
9+
diff = p2 * round_to_float(pi/4);
10+
x -= diff;
11+
printf("(x -= %s) -> %s\n", hexfloat(diff), hexfloat(x));
12+
endwhile
13+
diff = p2 * round_to_float(pi/4 - round_to_float(pi/4));
14+
x -= diff;
15+
printf("(x -= %s) -> %s\n", hexfloat(diff), hexfloat(x));
16+
printf("expected result: %s\n", hexfloat(expected));
17+
endfunction

math/generate_sindat.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/zsh
2+
3+
cd "${0%/*}"
4+
5+
function usage() {
6+
cat <<EOF
7+
Usage: $0
8+
9+
Options:
10+
--help|-h this message
11+
12+
EOF
13+
}
14+
15+
while (( $# > 0 )); do
16+
case "$1" in
17+
--help|-h) usage; exit ;;
18+
esac
19+
shift
20+
done
21+
22+
octave <<EOF
23+
ff=fopen("sincosf.dat", "w");
24+
fd=fopen("sincosd.dat", "w");
25+
26+
printf("Generating 100000 dp & sp sincos values [0, π/4] ");
27+
for i = 1:100000
28+
x=i * pi / 400000;
29+
fprintf(fd, "%.60f\t%.60f\t%.60f\n", x, sin(x), cos(x));
30+
x=round_to_float(x);
31+
fprintf(ff, "%.40f\t%.50f\t%.50f\n", x, sin(x), cos(x));
32+
printf("\033[4D%3i%%", floor(i/1000));
33+
endfor
34+
EOF
35+
36+
# vim: sw=2 et

math/hexdouble.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function r = hexdouble(x)
2+
if (signbit(x))
3+
s = "-";
4+
else
5+
s = "";
6+
endif
7+
x = abs(x);
8+
e = floor(log2(x));
9+
m = round((x*2^-e - 1) * 2^52);
10+
r = sprintf("%s0x1.%013xp%i", s, m, e);
11+
endfunction

math/hexfloat.m

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function r = hexfloat(x)
2+
if (x == 0)
3+
r = "0x0.000000p0";
4+
return;
5+
endif
6+
if (signbit(x))
7+
s = "-";
8+
else
9+
s = "";
10+
endif
11+
x = abs(x);
12+
e = floor(log2(x));
13+
m = roundb((x*2^-e - 1) * 2^23) * 2;
14+
r = sprintf("%s0x1.%06xp%i", s, m, e);
15+
endfunction

math/mycos.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function y = mycos (x)
2+
x2 = x.*x;
3+
y = 0;
4+
y = y .* x2 + to_double(0xAC00000000000, -45);
5+
y = y .* x2 - to_double(0x9394000000000, -37);
6+
y = y .* x2 + to_double(0x1EED8C0000000, -29);
7+
y = y .* x2 - to_double(0x27E4FB7400000, -22);
8+
y = y .* x2 + to_double(0xA01A01A018000, -16);
9+
y = y .* x2 - to_double(0x6C16C16C16C00, -10);
10+
y = y .* x2 + to_double(0x5555555555554, -5);
11+
y = y .* (x2 .* x2) - .5 * x2 + 1.;
12+
endfunction

math/mysin.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function y = mysin (x)
2+
x2 = x.*x;
3+
y = 0;
4+
y = (y - to_double(0xACF0000000000 + 0, -41)) .* x2;
5+
y = (y + to_double(0x6124400000000 + 0, -33)) .* x2;
6+
y = (y - to_double(0xAE64567000000 + 0, -26)) .* x2;
7+
y = (y + to_double(0x71DE3A5540000 + 0, -19)) .* x2;
8+
y = (y - to_double(0xa01a01a01a000 + 0, -13)) .* x2;
9+
y = (y + to_double(0x1111111111110 + 0, -7)) .* x2;
10+
y = (y - to_double(0x5555555555555 + 0, -3)) .* x2;
11+
y = (y + 1) .* x;
12+
endfunction

math/print_hexfloat.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function r = hexfloat(x)
2+
if (signbit(x))
3+
s = "-";
4+
else
5+
s = "";
6+
endif
7+
x = abs(x);
8+
e = floor(log2(x));
9+
m = round((x*2^-e - 1) * 2^23) * 2;
10+
r = sprintf("%s0x1.%xp%i", s, m, e);
11+
endfunction

math/round_to_float.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function x = round_to_float(x)
2+
if(x == 0)
3+
return;
4+
endif
5+
s = sign(x);
6+
x = abs(x);
7+
e = floor(log2(x));
8+
m = roundb((x.*2.^-e - 1) .* 2.^23);
9+
x = s .* (m .* 2.^-23 + 1) .* 2.^e;
10+
endfunction

0 commit comments

Comments
 (0)