News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Multiplier table

Started by jj2007, July 09, 2009, 10:50:41 AM

Previous topic - Next topic

jj2007

I need a table of REAL10 variables ranging from 1.0e-150 to 1.0e+150. With the FPU, I get small rounding errors. Is it possible to do that without the FPU, working directly on mantissa and exponent of the Real10???

Below a snippet for displaying Real10 content.

invoke PrintR10, jr1

PrintR10 proc arg10:Real10
LOCAL LocBuffer[100]:BYTE
pushad
lea esi, LocBuffer
print chr$(13, 10, "9876543210987654", 13, 10)
mov eax, dword ptr arg10
mov edx, dword ptr arg10[4]
movzx ecx, word ptr arg10[8]
pushad
invoke dw2bin_ex, ecx, esi
lea edx, [esi+16]
print edx, 13, 10
print "32109876543210987654321098765432 10987654321098765432109876543210", 13, 10
popad
pushad
invoke dw2bin_ex, edx, esi
print esi, " "
popad
invoke dw2bin_ex, eax, esi
print esi, 13, 10
popad
ret
PrintR10 endp


dedndave

you mean randomly generated values ?
the 80-bit float format is relatively simple
1 bit for sign
15 bits for exponent
64 bits for mantissa
exponent bias = 16383
all 1's in the exponent is a special value - do not use to make normals

jj2007

Quote from: dedndave on July 09, 2009, 12:37:20 PM
you mean randomly generated values ?

No, I mean exact values:

1.0e-150
1.0e-149
...
1.0e+149
1.0e+150

Multiplying a seed of 1.0e-150 repeatedly by 10.0 (exact, Real10) produces very small rounding errors, so I wonder whether working directly on the number in memory could yield exact ones... ::)

dedndave

ohhhhhhhhhhhhhhhhhhh
well - sure - a "str2float" is what you want
i dunno what you are asking for, i guess, Jochen
still early, here - lol - first cup of coffee

jj2007

Quote from: dedndave on July 09, 2009, 12:56:39 PM
ohhhhhhhhhhhhhhhhhhh
well - sure - a "str2float" is what you want
i dunno what you are asking for, i guess, Jochen
still early, here - lol - first cup of coffee

> str2float

No strings involved yet - just Real10 to Real10
:bg

Jimg

The exponent is easy enough to get (*log2), but if the mantissa were easy, we'd apply the process to converting any float to string.

You already know the initial value of 1.0e-150 is incorrect (inexact), so we can't get correct values by simply multiplying.

Perhaps if you started with a higher precision (e.g. 24 bytes would give 240 bits to lose) mantissa value.  It's easy to multiply exactly by 10 manually.

It would be really nice if we could efficiently generate these value as needed.  300 values isn't too bad for real8's, but 9800 for real10's is rather excessive.

I'm using a modification of the Tim Roberts scheme in masmlib.   Takes about 100 predefined values to cover the full range of real10's, and three multiplies to get a final value at execution.

So far the timing tests are very encouraging if I could just figure out how to efficiently round up .9999999999999999999999  to 1. before I generated all the digits :(

dedndave

well - for the 80-bit value of Pi, I used my 64-bit unsigned integer to ascii decimal routine to convert the mantissa
(my routine is the slowest one presented, but I have a great degree of confidence in the result string)
i then performed division by 2 on the string 62 times and placed a decimal point at the appropriate place to arive at the string
(62 = the exponent with the bias removed)

this is a bit tedious and slow, but it demonstrates one method of converting the value to a string
it results in "the" correct string - i.e. it represents the true binary value with no rounding error
many of the decimal digits were unusable, of course - only 20 digits maximum may be reliable

i am not suggesting this as a method, but it shows how it works
of course, if you are only generating the table one time, you don't care how fast it is

dedndave

for generating the table you want, it may be simpler to write a small program
to generate the ASM text file

dt 1.0e-150
dt 1.0e-149
...
dt 1.0e+149
dt 1.0e+150

of course, a little toil woth copy/paste could do the same thing
it's only 30 decades - lol
create one decade (or 2, maybe) by hand, then copy it and modify the copy

dedndave

#8
about 15 minutes using the toil method - lol
that'll be $50, Jochen, my friend - dunno what that is in lira

        dt 1.0e-150,1.0e-149,1.0e-148,1.0e-147,1.0e-146
        dt 1.0e-145,1.0e-144,1.0e-143,1.0e-142,1.0e-141

        dt 1.0e-140,1.0e-139,1.0e-138,1.0e-137,1.0e-136
        dt 1.0e-135,1.0e-134,1.0e-133,1.0e-132,1.0e-131

        dt 1.0e-130,1.0e-129,1.0e-128,1.0e-127,1.0e-126
        dt 1.0e-125,1.0e-124,1.0e-123,1.0e-122,1.0e-121

        dt 1.0e-120,1.0e-119,1.0e-118,1.0e-117,1.0e-116
        dt 1.0e-115,1.0e-114,1.0e-113,1.0e-112,1.0e-111

        dt 1.0e-110,1.0e-109,1.0e-108,1.0e-107,1.0e-106
        dt 1.0e-105,1.0e-104,1.0e-103,1.0e-102,1.0e-101

        dt 1.0e-100,1.0e-99,1.0e-98,1.0e-97,1.0e-96
        dt 1.0e-95,1.0e-94,1.0e-93,1.0e-92,1.0e-91

        dt 1.0e-90,1.0e-89,1.0e-88,1.0e-87,1.0e-86
        dt 1.0e-85,1.0e-84,1.0e-83,1.0e-82,1.0e-81

        dt 1.0e-80,1.0e-79,1.0e-78,1.0e-77,1.0e-76
        dt 1.0e-75,1.0e-74,1.0e-73,1.0e-72,1.0e-71

        dt 1.0e-70,1.0e-69,1.0e-68,1.0e-67,1.0e-66
        dt 1.0e-65,1.0e-64,1.0e-63,1.0e-62,1.0e-61

        dt 1.0e-60,1.0e-59,1.0e-58,1.0e-57,1.0e-56
        dt 1.0e-55,1.0e-54,1.0e-53,1.0e-52,1.0e-51

        dt 1.0e-50,1.0e-49,1.0e-48,1.0e-47,1.0e-46
        dt 1.0e-45,1.0e-44,1.0e-43,1.0e-42,1.0e-41

        dt 1.0e-40,1.0e-39,1.0e-38,1.0e-37,1.0e-36
        dt 1.0e-35,1.0e-34,1.0e-33,1.0e-32,1.0e-31

        dt 1.0e-30,1.0e-29,1.0e-28,1.0e-27,1.0e-26
        dt 1.0e-25,1.0e-24,1.0e-23,1.0e-22,1.0e-21

        dt 1.0e-20,1.0e-19,1.0e-18,1.0e-17,1.0e-16
        dt 1.0e-15,1.0e-14,1.0e-13,1.0e-12,1.0e-11

        dt 1.0e-10,1.0e-9,1.0e-8,1.0e-7,1.0e-6
        dt 1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1

        dt 1.0

        dt 1.0e+1,1.0e+2,1.0e+3,1.0e+4,1.0e+5
        dt 1.0e+6,1.0e+7,1.0e+8,1.0e+9,1.0e+10

        dt 1.0e+11,1.0e+12,1.0e+13,1.0e+14,1.0e+15
        dt 1.0e+16,1.0e+17,1.0e+18,1.0e+19,1.0e+20

        dt 1.0e+21,1.0e+22,1.0e+23,1.0e+24,1.0e+25
        dt 1.0e+26,1.0e+27,1.0e+28,1.0e+29,1.0e+30

        dt 1.0e+31,1.0e+32,1.0e+33,1.0e+34,1.0e+35
        dt 1.0e+36,1.0e+37,1.0e+38,1.0e+39,1.0e+40

        dt 1.0e+41,1.0e+42,1.0e+43,1.0e+44,1.0e+45
        dt 1.0e+46,1.0e+47,1.0e+48,1.0e+49,1.0e+50

        dt 1.0e+51,1.0e+52,1.0e+53,1.0e+54,1.0e+55
        dt 1.0e+56,1.0e+57,1.0e+58,1.0e+59,1.0e+60

        dt 1.0e+61,1.0e+62,1.0e+63,1.0e+64,1.0e+65
        dt 1.0e+66,1.0e+67,1.0e+68,1.0e+69,1.0e+70

        dt 1.0e+71,1.0e+72,1.0e+73,1.0e+74,1.0e+75
        dt 1.0e+76,1.0e+77,1.0e+78,1.0e+79,1.0e+80

        dt 1.0e+81,1.0e+82,1.0e+83,1.0e+84,1.0e+85
        dt 1.0e+86,1.0e+87,1.0e+88,1.0e+89,1.0e+90

        dt 1.0e+91,1.0e+92,1.0e+93,1.0e+94,1.0e+95
        dt 1.0e+96,1.0e+97,1.0e+98,1.0e+99,1.0e+100

        dt 1.0e+101,1.0e+102,1.0e+103,1.0e+104,1.0e+105
        dt 1.0e+106,1.0e+107,1.0e+108,1.0e+109,1.0e+110

        dt 1.0e+111,1.0e+112,1.0e+113,1.0e+114,1.0e+115
        dt 1.0e+116,1.0e+117,1.0e+118,1.0e+119,1.0e+120

        dt 1.0e+121,1.0e+122,1.0e+123,1.0e+124,1.0e+125
        dt 1.0e+126,1.0e+127,1.0e+128,1.0e+129,1.0e+130

        dt 1.0e+131,1.0e+132,1.0e+133,1.0e+134,1.0e+135
        dt 1.0e+136,1.0e+137,1.0e+138,1.0e+139,1.0e+140

        dt 1.0e+141,1.0e+142,1.0e+143,1.0e+144,1.0e+145
        dt 1.0e+146,1.0e+147,1.0e+148,1.0e+149,1.0e+150

jj2007

Quote from: dedndave on July 09, 2009, 03:33:39 PM
about 15 minutes using the toil method - lol
that'll be $50, Jochen, my friend - dunno what that is in lira

About 1 minute in Excel, Dave - but that costs 3kbyte and was exactly the reason why I want to generate that table :bg

dedndave

ok - but
assemble that text
look at the binary values generated for the table
see if you can sherlock an algorithm to generate it

also, the errors are cumulative because, in each pass of the algorithm, you use the value from the previous pass
see if you can eliminate that accumulation by making more direct calculations

jj2007

Quote from: dedndave on July 09, 2009, 06:06:42 PM
ok - but
assemble that text
look at the binary values generated for the table
see if you can sherlock an algorithm to generate it

also, the errors are cumulative because, in each pass of the algorithm, you use the value from the previous pass
see if you can eliminate that accumulation by making more direct calculations

Well, that's exactly what I have been doing so far... the + and - indicate for which n a correction was needed.

7+      1        1.000000000000000000e-137
8-      2        1.000000000000000000e-136
9-      3        1.000000000000000000e-135
10+     4        1.000000000000000000e-134
17+     5        1.000000000000000000e-127
18-     6        1.000000000000000000e-126
19-     7        1.000000000000000000e-125
20+     8        1.000000000000000000e-124
21+     9        1.000000000000000000e-123
22-     10       1.000000000000000000e-122
25+     11       1.000000000000000000e-119
26-     12       1.000000000000000000e-118
27-     13       1.000000000000000000e-117
...
296+    131      1.000000000000000000e+152
297-    132      1.000000000000000000e+153
298-    133      1.000000000000000000e+154
299+    134      1.000000000000000000e+155

dedndave

well, i think you are back to str2float
because you can surely generate the strings without rounding errors - then use str2float to get the real
this method relies on the str2float to generate good values, as well

EDIT
no way you wrote that spreadsheet in 1 minute - lol

EDIT
it may help if you generate the table, starting with 1.0e+150 and divide instead of multiplying - i dunno
it would make sense because you are gaining resolution as you go, in a way
if all else fails, you can make a very long string in allocated memory and do the division by moving an imaginary decimal point (i.e. dec a ptr)
let me give this some thought - i will get back to you later

jj2007

The idea to use StrToFloat is cute but yields only REAL8 results: 1.0000000000000000200E-100
Same for a2r10, strangely enough.

dedndave

ok - i have a plan - lol
for one thing, you should start with 1.0 and divide to make the lower portion of the table
and start with 1.0 and multiply to make the upper portion
1.0 expressed as a real is precise (i.e. the decimal evaluation is exactly equal to the binary representation)
i think i have a way to do it, but i have some outside work i wanted to do today before it gets any hotter
i will let it tumble around in my head while i take care of that