@@ -2064,10 +2064,10 @@ def multiword2mpf(ctx, mw):
20642064    return  s 
20652065
20662066
2067- def  mpf2multiword (dtype , x , p = None , max_length = None ):
2067+ def  mpf2multiword (dtype , x , p = None , max_length = None ,  sexp = 0 ):
20682068    """Return a list of fixed-width floating point numbers such that 
20692069
2070-       x == sum([float2mpf(mpmath.mp, v) for v in result]) + O(smallest subnormal of dtype ) 
2070+       x == sum([float2mpf(mpmath.mp, v) / (2 ** (i * sexp))  for i,  v in enumerate( result) ]) + O(... ) 
20712071
20722072    where x is a mpmath mpf instance. 
20732073
@@ -2096,6 +2096,69 @@ def mpf2multiword(dtype, x, p=None, max_length=None):
20962096      len(result) <= max_length 
20972097
20982098    holds. 
2099+ 
2100+     The truncation from the limited exponent size can be avoided by 
2101+     specifying positive value to the scaling exponent argument sexp: 
2102+ 
2103+     Take x = pi: 
2104+     p       | sexp        | maximal x precision in bits 
2105+     --------+-------------+---------------------------- 
2106+     float16 
2107+     2       | 0,1,...     | 11,11,... 
2108+     3       | 0,1,...[4]  | 26,38,49,49,[49],40,25,18,17,11,... 
2109+     4       | 0,1,...[5]  | 26,33,42,65,105,[105],63,34,24,20,... 
2110+     5       | 0,1,...[6]  | 26,33,38,47,78,105,[105],69,33,29,... 
2111+     6       | 0,1,...[7]  | 26,30,38,44,59,82,105,[105],73,38, 
2112+     7       | 0,1,...[8]  | 26,30,34,42,54,61,87,150,[800],109,44,... 
2113+     8       | 0,1,...[9]  | 26,29,33,38,42,53,63,76,122,[2978],187,... 
2114+     9       | 0,1,...[11] | ...,99,106,135,208,[357],99,... 
2115+     10      | 0,1,...[11] | ...,155,[1096],249,99,... 
2116+     11      | 0,1,...[13] | ...,99,114,208,451,150,... 
2117+     float32 
2118+     4       | 0,1,...[10] | ...,105,105,...,[105],103,99,... 
2119+     5       | 0,1,...[13] | ...,105,105,...,[105],93,... 
2120+     6       | 0,1,...[16] | ...,105,105,...,[105],92,... 
2121+     7       | 0,1,...[9]  | ...,299,396,602,912,[912],871,... 
2122+     8       | 0,1,...[9]  | ...,676,1343,[4280],1061,.... 
2123+     9       | 0,1,...[10] | ...,1205,[3726],1600,... 
2124+     10      | 0,1,...[11] | ...,1851,[16429],1182 
2125+     11      | 0,1,...[12]   | ...,1462,[>44000],1797 
2126+     12      | 0,1,...[13]   | ...,1823,[>50000],... 
2127+     13      | 0,1,...[14]   | ...,1609,[>50000],1987,... 
2128+     ... 
2129+     24      | 0,1,...[25]   | ...,1738,3202,[>50000],... 
2130+     float64 
2131+     8       | 0,1,...[11]     | ...,3188,4280,4280,4280,4280,[4280],3129,... 
2132+     12      | 0,1,...[13]     | ...,13847,[>50000],13356,... 
2133+     ... 
2134+     53      | 0,1,...,53,[..] | ...,55030,[...],... 
2135+ 
2136+     From the above table follows a relation 
2137+ 
2138+       sexp == p + 1 
2139+ 
2140+     that maximizes the precision of x that can be represented exactly 
2141+     as a multiword. 
2142+ 
2143+     The maximal bit-size of the multiword representation depends on 
2144+     the value of x. For example, take sexp = p + 1, then for 
2145+     p=1,...,11 the maximal bit-size sequence is as follows [float16]: 
2146+ 
2147+       pi    : 4,4, 49,105,105,105,800,2978, 208,1096, 208 
2148+       log(2): 6,6,101, 19,101,139,101, 107,1345, 830, 596 
2149+       2 / pi: 5,6,  6,129,127,322,324,2299,1093,1127,1339 
2150+ 
2151+     that is, the optimal value for p also depends on the value of x. 
2152+ 
2153+     The dtype dependence of the maximal bit-size sequence is as 
2154+     follows [2 / pi]: 
2155+ 
2156+       float16: 5,6,6,129,127,322,324,2299,1093,1127,1339 
2157+       float32: 5,6,6,129,127,322,324,2299,2835,[>5000] 
2158+       float64: 5,6,6,129,127,322,324,2299,[>5000] 
2159+ 
2160+     that is, the optimal value for p increases with increasing dtype 
2161+     bitsize. 
20992162    """ 
21002163    sign , man , exp , bc  =  x ._mpf_ 
21012164    mpf  =  x .context .mpf 
@@ -2122,9 +2185,9 @@ def mpf2multiword(dtype, x, p=None, max_length=None):
21222185            offset  -=  d 
21232186            man1  =  (man  &  (mask  <<  offset )) >>  offset 
21242187            bl1  =  man1 .bit_length ()
2125-         exp1  =  exp  +  offset 
2188+         exp1  =  exp  +  offset   +   len ( result )  *   sexp 
21262189        x1  =  mpf2float (dtype , mpf ((sign , man1 , exp1 , bl1 )))
2127-         if  x1  ==  dtype (0 ):
2190+         if  x1  ==  dtype (0 )  and   offset   ==   0 :
21282191            # result represents truncated x 
21292192            break 
21302193        result .append (x1 )
0 commit comments