QDouble.st
changeset 4393 4084ca142033
parent 4392 a64fe2606d82
child 4395 3a01a83b6303
equal deleted inserted replaced
4392:a64fe2606d82 4393:4084ca142033
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 2017 by eXept Software AG
     4  COPYRIGHT (c) 2017 by eXept Software AG
     3               All Rights Reserved
     5               All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
  1043 !
  1045 !
  1044 
  1046 
  1045 - aNumber
  1047 - aNumber
  1046     "return the sum of the receiver and the argument, aNumber"
  1048     "return the sum of the receiver and the argument, aNumber"
  1047 
  1049 
  1048     ^ (aNumber negated) sumFromQDouble:self
  1050     ^ self + (aNumber negated)
  1049 
  1051 
  1050     "
  1052     "
  1051      (QDouble fromFloat:1e20) asDoubleArray
  1053      (QDouble fromFloat:1e20) asDoubleArray
  1052      ((QDouble fromFloat:1e20) - (QDouble fromFloat:1.0)) asDoubleArray
  1054      ((QDouble fromFloat:1e20) - (QDouble fromFloat:1.0)) asDoubleArray
  1053      (QDouble fromFloat:1e-20) asDoubleArray
  1055      (QDouble fromFloat:1e-20) asDoubleArray
  1054      ((QDouble fromFloat:1e-20) - (QDouble fromFloat:1.0)) asDoubleArray
  1056      ((QDouble fromFloat:1e-20) - (QDouble fromFloat:1.0)) asDoubleArray
  1055      ((QDouble fromFloat:2.0) - (QDouble fromFloat:1.0)) asDoubleArray
  1057      ((QDouble fromFloat:2.0) - (QDouble fromFloat:1.0)) asDoubleArray
       
  1058      
       
  1059      ((QDouble fromFloat:2.0) - (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)) asDoubleArray
       
  1060      ((QDouble fromFloat:1e-20) - (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)) asDoubleArray
  1056     "
  1061     "
  1057 
  1062 
  1058     "Created: / 12-06-2017 / 23:41:39 / cg"
  1063     "Created: / 12-06-2017 / 23:41:39 / cg"
       
  1064     "Modified (comment): / 15-06-2017 / 00:34:41 / cg"
  1059 !
  1065 !
  1060 
  1066 
  1061 / aNumber
  1067 / aNumber
  1062     "return the quotient of the receiver and the argument, aNumber"
  1068     "return the quotient of the receiver and the argument, aNumber"
  1063 
  1069 
  1064     ^ aNumber quotientFromQDouble:self
  1070     ^ aNumber quotientFromQDouble:self
  1065 
  1071 
  1066     "
  1072     "
  1067      ((QDouble fromFloat:1e20) / (QDouble fromFloat:2.0)) asDoubleArray
  1073      ((QDouble fromFloat:1e20) / (QDouble fromFloat:2.0)) asDoubleArray
       
  1074      
       
  1075      ((QDouble fromFloat:1.2345) / (QDouble fromFloat:10.0)) asDoubleArray
       
  1076      ((QDouble fromFloat:1.2345) / 10.0) asDoubleArray
       
  1077 
  1068     "
  1078     "
  1069 
  1079 
  1070     "Created: / 13-06-2017 / 17:59:09 / cg"
  1080     "Created: / 13-06-2017 / 17:59:09 / cg"
       
  1081     "Modified (comment): / 15-06-2017 / 00:14:26 / cg"
  1071 ! !
  1082 ! !
  1072 
  1083 
  1073 !QDouble methodsFor:'coercing & converting'!
  1084 !QDouble methodsFor:'coercing & converting'!
  1074 
  1085 
  1075 asDoubleArray
  1086 asDoubleArray
  1407 quotientFromQDouble:aQDouble
  1418 quotientFromQDouble:aQDouble
  1408     "sloppy"
  1419     "sloppy"
  1409     
  1420     
  1410     |q0 q1 q2 q3 r|
  1421     |q0 q1 q2 q3 r|
  1411 
  1422 
  1412     q0 := self d0 / aQDouble d0.
  1423     q0 := aQDouble d0 / self d0.
  1413     r := self - (aQDouble * q0).
  1424     "/ Stdout showCR:('q0: %1 (a[0]=%2; b[0]=%3)\n' bindWith:q0 with:self d0 with:aQDouble d0).
  1414 
  1425     r := aQDouble - (self * q0).
  1415     q1 := r d0 / aQDouble d0.
  1426     "/ Stdout showCR:('r: %1\n' bindWith:r asDoubleArray).
  1416     r := r - (aQDouble * q1).
  1427 
       
  1428     q1 := r d0 / self d0.
       
  1429     "/ Stdout showCR:('q1: %1 (r[0]=%2; b[0]=%3)\n' bindWith:q1 with:r d0 with:aQDouble d0).
       
  1430     r := r - (self * q1).
       
  1431     "/ Stdout showCR:('r: %1\n' bindWith:r asDoubleArray).
  1417     
  1432     
  1418     q2 := r d0 / aQDouble d0.
  1433     q2 := r d0 / self d0.
  1419     r := r - (aQDouble * q2).
  1434     "/ Stdout showCR:('q2: %1 (r[0]=%2; b[0]=%3)\n' bindWith:q2 with:r d0 with:aQDouble d0).
  1420 
  1435     r := r - (self * q2).
  1421     q3 := r d0 / aQDouble d0.
  1436     "/ Stdout showCR:('r: %1\n' bindWith:r asDoubleArray).
       
  1437 
       
  1438     q3 := r d0 / self d0.
       
  1439     "/ Stdout showCR:('q3: %1 (r[0]=%2; b[0]=%3)\n' bindWith:q3 with:r d0 with:aQDouble d0).
  1422 
  1440 
  1423     r := self class d0:q0 d1:q1 d2:q2 d3:q3.
  1441     r := self class d0:q0 d1:q1 d2:q2 d3:q3.
       
  1442     "/ Stdout showCR:('before renorm: %1\n' bindWith:r asDoubleArray).
  1424     r renorm.
  1443     r renorm.
       
  1444     "/ Stdout showCR:('after renorm: %1\n' bindWith:r asDoubleArray).
  1425     ^ r
  1445     ^ r
  1426 
  1446 
  1427     "
  1447     "
  1428      2.0 / (QDouble fromFloat:2.0)
  1448      2.0 / (QDouble fromFloat:2.0)
  1429      2.0 / (QDouble fromFloat:1.0)
  1449      2.0 / (QDouble fromFloat:1.0)
  1435      (QDouble fromFloat:1e20) / 2.0
  1455      (QDouble fromFloat:1e20) / 2.0
  1436      ((QDouble fromFloat:1.0) / 2.0) asFloat
  1456      ((QDouble fromFloat:1.0) / 2.0) asFloat
  1437      ((QDouble fromFloat:1e20 / 2.0)) asFloat
  1457      ((QDouble fromFloat:1e20 / 2.0)) asFloat
  1438      
  1458      
  1439      ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray
  1459      ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray
       
  1460 
       
  1461      ((QDouble fromFloat:10.0) quotientFromQDouble: (QDouble fromFloat:1.234)) asDoubleArray
       
  1462      ((QDouble fromFloat:1.234) / (QDouble fromFloat:10.0)) asDoubleArray
       
  1463      
       
  1464 q0: 1.234000e-01 (a[0]=1.234000e+00; b[0]=1.000000e+01)
       
  1465 a: 1.234000e+00/0.000000e+00/0.000000e+00/0.000000e+00
       
  1466 b: 1.000000e+01/0.000000e+00/0.000000e+00/0.000000e+00
       
  1467 (b * q0): 1.234000e+00/-2.775558e-17/0.000000e+00/0.000000e+00
       
  1468 r: 2.775558e-17/0.000000e+00/0.000000e+00/0.000000e+00
       
  1469 
       
  1470 q1: 2.775558e-18 (r[0]=2.775558e-17; b[0]=1.000000e+01)
       
  1471 r: -1.540744e-33/0.000000e+00/0.000000e+00/0.000000e+00
       
  1472 
       
  1473 q2: -1.540744e-34 (r[0]=-1.540744e-33; b[0]=1.000000e+01)
       
  1474 r: 8.552847e-50/0.000000e+00/0.000000e+00/0.000000e+00
       
  1475 
       
  1476 q3: 8.552847e-51 (r[0]=8.552847e-50; b[0]=1.000000e+01)
       
  1477 
       
  1478 before renorm: 1.234000e-01/2.775558e-18/-1.540744e-34/8.552847e-51
       
  1479 after renorm: 1.234000e-01/2.775558e-18/-1.540744e-34/8.552847e-51
       
  1480 1.234/10.0 is: 0.123400 / 0.000000 / -0.000000 / 0.000000
       
  1481 
       
  1482 
  1440     "
  1483     "
  1441 
  1484 
  1442     "Created: / 13-06-2017 / 17:50:35 / cg"
  1485     "Created: / 13-06-2017 / 17:50:35 / cg"
       
  1486     "Modified (comment): / 15-06-2017 / 01:02:05 / cg"
  1443 !
  1487 !
  1444 
  1488 
  1445 sumFromFloat:aFloat
  1489 sumFromFloat:aFloat
  1446 %{
  1490 %{
  1447     if (__isFloatLike(aFloat)) {
  1491     if (__isFloatLike(aFloat)) {
  1490         OBJ newQD;
  1534         OBJ newQD;
  1491         
  1535         
  1492 #ifndef QD_IEEE_ADD
  1536 #ifndef QD_IEEE_ADD
  1493         // sloppy_add...
  1537         // sloppy_add...
  1494 
  1538 
  1495         /*
  1539 # if 0
  1496         double s0, s1, s2, s3;
  1540         double s0, s1, s2, s3;
  1497         double t0, t1, t2, t3;
  1541         double t0, t1, t2, t3;
  1498         int savedCV;
  1542         int savedCV;
  1499 
  1543 
  1500         fpu_fix_start(&savedCV);
  1544         fpu_fix_start(&savedCV);
  1506         m_two_sum(s1, s1, t0, t0);
  1550         m_two_sum(s1, s1, t0, t0);
  1507         m_three_sum(s2, t0, t1);
  1551         m_three_sum(s2, t0, t1);
  1508         m_three_sum2(s3, t0, t2);
  1552         m_three_sum2(s3, t0, t2);
  1509         t0 = t0 + t1 + t3;
  1553         t0 = t0 + t1 + t3;
  1510 
  1554 
       
  1555         m_renorm5(s0, s1, s2, s3, t0);
  1511         fpu_fix_end(&savedCV);
  1556         fpu_fix_end(&savedCV);
  1512         m_renorm5(s0, s1, s2, s3, t0);
  1557 
  1513         return qd_real(s0, s1, s2, s3, t0);
  1558         __qNew_qdReal(newQD, s0, s1, s2, s3);
  1514         */
  1559         RETURN(newQD);                 
       
  1560 # else
  1515 
  1561 
  1516         /* Same as above, but addition re-organized to minimize
  1562         /* Same as above, but addition re-organized to minimize
  1517            data dependency ... unfortunately some compilers are
  1563            data dependency ... unfortunately some compilers are
  1518            not very smart to do this automatically */
  1564            not very smart to do this automatically */
  1519         double s0, s1, s2, s3;
  1565         double s0, s1, s2, s3;
  1562         /* renormalize */
  1608         /* renormalize */
  1563         m_renorm5(s0, s1, s2, s3, t0);
  1609         m_renorm5(s0, s1, s2, s3, t0);
  1564         fpu_fix_end(&savedCV);
  1610         fpu_fix_end(&savedCV);
  1565         __qNew_qdReal(newQD, s0, s1, s2, s3);
  1611         __qNew_qdReal(newQD, s0, s1, s2, s3);
  1566         RETURN(newQD);                 
  1612         RETURN(newQD);                 
       
  1613 # endif
  1567 #else
  1614 #else
  1568         // ieee_add...
  1615         // ieee_add...
  1569         int i, j, k;
  1616         int i, j, k;
  1570         double s, t;
  1617         double s, t;
  1571         double u, v;   /* double-length accumulator */
  1618         double u, v;   /* double-length accumulator */
  1635      (1e-20 + (QDouble fromFloat:1.0)) asDoubleArray
  1682      (1e-20 + (QDouble fromFloat:1.0)) asDoubleArray
  1636      (1e20 + (QDouble fromFloat:1.0)) asDoubleArray
  1683      (1e20 + (QDouble fromFloat:1.0)) asDoubleArray
  1637    "
  1684    "
  1638 
  1685 
  1639     "Created: / 12-06-2017 / 21:15:43 / cg"
  1686     "Created: / 12-06-2017 / 21:15:43 / cg"
  1640     "Modified: / 14-06-2017 / 11:44:53 / cg"
  1687     "Modified: / 15-06-2017 / 00:49:10 / cg"
  1641 ! !
  1688 ! !
  1642 
  1689 
  1643 !QDouble methodsFor:'inspecting'!
  1690 !QDouble methodsFor:'inspecting'!
  1644 
  1691 
  1645 inspectorExtraAttributes
  1692 inspectorExtraAttributes
  1782     "Created: / 13-06-2017 / 01:27:58 / cg"
  1829     "Created: / 13-06-2017 / 01:27:58 / cg"
  1783 ! !
  1830 ! !
  1784 
  1831 
  1785 !QDouble methodsFor:'printing & storing'!
  1832 !QDouble methodsFor:'printing & storing'!
  1786 
  1833 
  1787 printDigitsOn:outStream precision:precision exponentInto:expn
  1834 digitsWithPrecision:precision
  1788     |numDigits r e i d|
  1835     "generate the digits and exponent"
       
  1836     
       
  1837     |numDigits r exp i d out str|
  1789 
  1838 
  1790     numDigits := precision+1. "/ number of digits
  1839     numDigits := precision+1. "/ number of digits
  1791     r := self abs.
  1840     r := self abs.
  1792     self d0 = 0.0 ifTrue:[
  1841     self d0 = 0.0 ifTrue:[
  1793         expn value:0.
  1842         ^ { String new:precision withAll:$0 . 0 }
  1794         precision timesRepeat:[ outStream nextPut:$0 ].
  1843     ].
       
  1844 
       
  1845     out := WriteStream on:(String new:precision+5).
       
  1846 
       
  1847     "/ determine approx. exponent
       
  1848     exp := self d0 abs log10 floor.
       
  1849     exp < -300 ifTrue:[
       
  1850         r := r * (10.0 raisedToInteger:300).
       
  1851         r := r / (10.0 raisedToInteger:(exp+300)).
       
  1852     ] ifFalse:[
       
  1853         exp > 300 ifTrue:[
       
  1854 self halt.
       
  1855 "/            r := ldexpr(r, -53);
       
  1856 "/            r := r / qd_real(10.0) ^ exp;
       
  1857 "/            r := ldexp(r, 53);
       
  1858         ] ifFalse:[
       
  1859             r := r / (10.0 asQDouble raisedTo:exp).
       
  1860         ]
       
  1861     ].
       
  1862 
       
  1863     "/ Fix exponent if we are off by one
       
  1864     (r >= 10.0) ifTrue:[
       
  1865         r := r / 10.0.
       
  1866         exp := exp + 1.
       
  1867     ] ifFalse:[
       
  1868         (r < 1.0) ifTrue:[
       
  1869             r := r * 10.0.
       
  1870             exp := exp - 1.
       
  1871         ]
       
  1872     ].
       
  1873 
       
  1874     ((r >= 10.0) or:[ r < 1.0 ]) ifTrue:[
       
  1875         self error:'can''t compute exponent.'.
       
  1876     ].
       
  1877 
       
  1878     "/ Extract the digits
       
  1879     1 to:numDigits do:[:i |
       
  1880         d := r d0 truncated.
       
  1881         r := r - d.
       
  1882         r := r * 10.0.
       
  1883 
       
  1884         out nextPut:($0 + d).
       
  1885     ].
       
  1886 
       
  1887     str := out contents.
       
  1888     
       
  1889     "/ Fix out-of-range digits.
       
  1890     "/ huh? what is this???? 
       
  1891     "/ how can an "out-of-range" digit appear???
       
  1892     numDigits to:2 by:-1 do:[:i |
       
  1893         (str at:i) < $0 ifTrue:[
       
  1894 self halt.
       
  1895             str at:i-1 put:(str at:i-1) - 1.
       
  1896             str at:i put:(str at:i) + 10.
       
  1897         ] ifFalse:[
       
  1898             (str at:i) > $9 ifTrue:[
       
  1899 self halt.
       
  1900                 str at:i-1 put:(str at:i-1) + 1.
       
  1901                 str at:i put:(str at:i) - 10.
       
  1902             ].    
       
  1903         ].
       
  1904     ].    
       
  1905     
       
  1906     str first <= $0 ifTrue:[
       
  1907         self error:'non-positive leading digit'
       
  1908     ].
       
  1909 
       
  1910     "/ Round, handle carry 
       
  1911     (str at:numDigits) >= $5 ifTrue:[
       
  1912         str at:numDigits-1 put:(str at:numDigits-1) + 1.
       
  1913         i := numDigits-1.
       
  1914         [i > 1 and:[(str at:i) > $9]] whileTrue:[
       
  1915             str at:i put:(str at:i) - 10.
       
  1916             i := i - 1.
       
  1917             str at:i put:(str at:i) + 1.
       
  1918         ]    
       
  1919     ].    
       
  1920 
       
  1921     "/ If first digit is 10, shift everything.
       
  1922     str first > $9 ifTrue:[
       
  1923         exp := exp + 1.
       
  1924         str at:1 put:$0.
       
  1925         str := '1',str
       
  1926     ].    
       
  1927     ^ { (str copyTo:precision) . exp }
       
  1928     
       
  1929     "
       
  1930      1.2345 asQDouble digitsWithPrecision:5 -> #('12345' 0)
       
  1931      12.345 asQDouble digitsWithPrecision:5 -> #('12345' 1)
       
  1932      12345 asQDouble digitsWithPrecision:5 -> #('12345' 4)
       
  1933      12345.1 asQDouble digitsWithPrecision:5 -> #('12345' 4)
       
  1934      12345.9 asQDouble digitsWithPrecision:5 -> #('12346' 4)
       
  1935  
       
  1936      1.2345 asQDouble / 10.0 asQDouble
       
  1937      1.2345 asQDouble / 10.0 
       
  1938     "
       
  1939 
       
  1940     "Created: / 15-06-2017 / 09:10:01 / cg"
       
  1941 !
       
  1942 
       
  1943 digitsWithPrecision:precision exponentInto:expnHolder
       
  1944     "generate the digits and return exponent info"
       
  1945     
       
  1946     |numDigits r exp i d out str|
       
  1947 
       
  1948     numDigits := precision+1. "/ number of digits
       
  1949     r := self abs.
       
  1950     self d0 = 0.0 ifTrue:[
       
  1951         expnHolder value:0.
       
  1952         ^ String new:precision withAll:$0
       
  1953     ].
       
  1954 
       
  1955     out := WriteStream on:(String new:precision+5).
       
  1956 
       
  1957     "/ determine approx. exponent
       
  1958     exp := self d0 abs log10 floor.
       
  1959     exp < -300 ifTrue:[
       
  1960         r := r * (10.0 raisedToInteger:300).
       
  1961         r := r / (10.0 raisedToInteger:(exp+300)).
       
  1962     ] ifFalse:[
       
  1963         exp > 300 ifTrue:[
       
  1964 self halt.
       
  1965 "/            r := ldexpr(r, -53);
       
  1966 "/            r := r / qd_real(10.0) ^ exp;
       
  1967 "/            r := ldexp(r, 53);
       
  1968         ] ifFalse:[
       
  1969             r := r / (10.0 asQDouble raisedTo:exp).
       
  1970         ]
       
  1971     ].
       
  1972 
       
  1973     "/ Fix exponent if we are off by one
       
  1974     (r >= 10.0) ifTrue:[
       
  1975         r := r / 10.0.
       
  1976         exp := exp + 1.
       
  1977     ] ifFalse:[
       
  1978         (r < 1.0) ifTrue:[
       
  1979             r := r * 10.0.
       
  1980             exp := exp - 1.
       
  1981         ]
       
  1982     ].
       
  1983 
       
  1984     ((r >= 10.0) or:[ r < 1.0 ]) ifTrue:[
       
  1985         self error:'can''t compute exponent.'.
       
  1986     ].
       
  1987 
       
  1988     "/ Extract the digits
       
  1989     1 to:numDigits do:[:i |
       
  1990         d := r d0 truncated.
       
  1991         r := r - d.
       
  1992         r := r * 10.0.
       
  1993 
       
  1994         out nextPut:($0 + d).
       
  1995     ].
       
  1996 
       
  1997     str := out contents.
       
  1998     
       
  1999     "/ Fix out-of-range digits.
       
  2000     "/ huh? what is this???? 
       
  2001     "/ how can an "out-of-range" digit appear???
       
  2002     i := numDigits.
       
  2003     [i > 1] whileTrue:[
       
  2004         (str at:i) < $0 ifTrue:[
       
  2005             self halt.
       
  2006             str at:i-1 put:(str at:i-1) - 1.
       
  2007             str at:i put:(str at:i) + 10.
       
  2008         ] ifFalse:[
       
  2009             (str at:i) > $9 ifTrue:[
       
  2010                 self halt.
       
  2011                 str at:i-1 put:(str at:i-1) + 1.
       
  2012                 str at:i put:(str at:i) - 10.
       
  2013             ].    
       
  2014         ].
       
  2015         i := i - 1.
       
  2016     ].    
       
  2017     
       
  2018     (str at:1) <= $0 ifTrue:[
       
  2019         self error:'non-positive leading digit'
       
  2020     ].
       
  2021 
       
  2022     "/ Round, handle carry 
       
  2023     (str at:numDigits) >= $5 ifTrue:[
       
  2024         str at:numDigits-1 put:(str at:numDigits-1) + 1.
       
  2025         i := numDigits-1.
       
  2026         [i > 1 and:[(str at:i) > $9]] whileTrue:[
       
  2027             str at:i put:(str at:i) - 10.
       
  2028             i := i - 1.
       
  2029             str at:i put:(str at:i) + 1.
       
  2030         ]    
       
  2031     ].    
       
  2032 
       
  2033     "/ If first digit is 10, shift everything.
       
  2034     (str at:1) > $9 ifTrue:[
       
  2035         exp := exp + 1.
       
  2036         str at:1 put:$0.
       
  2037         str := '1',str
       
  2038     ].    
       
  2039     expnHolder value:exp.
       
  2040     ^ (str copyTo:precision).
       
  2041     
       
  2042     "
       
  2043      1.2345 asQDouble digitsWithPrecision:5 exponentInto:[:e | Transcript showCR:e] -> '12345' / 0
       
  2044      12.345 asQDouble digitsWithPrecision:5 exponentInto:[:e | Transcript showCR:e] -> '12345' / 1
       
  2045      12345 asQDouble digitsWithPrecision:5 exponentInto:[:e | Transcript showCR:e]
       
  2046      12345.1 asQDouble digitsWithPrecision:5 exponentInto:[:e | Transcript showCR:e]
       
  2047      12345.9 asQDouble digitsWithPrecision:5 exponentInto:[:e | Transcript showCR:e]
       
  2048  
       
  2049      1.2345 asQDouble / 10.0 asQDouble
       
  2050      1.2345 asQDouble / 10.0 
       
  2051     "
       
  2052 
       
  2053     "Created: / 15-06-2017 / 09:05:42 / cg"
       
  2054 !
       
  2055 
       
  2056 printOn:aStream
       
  2057     "return a printed representation of the receiver"
       
  2058 
       
  2059     self d1 = 0.0 ifTrue:[
       
  2060         self d0 printOn:aStream.
  1795         ^ self.
  2061         ^ self.
  1796     ].
  2062     ].
  1797 
  2063     self
  1798     "/ determine approx. exponent
  2064         printOn:aStream precision:0 width:0 
  1799     e := self d0 abs log10 floor.
  2065         fixed:false showPositive:false uppercase:false fillChar:(Character space)
  1800     self halt.
  2066 
  1801     e < -300 ifTrue:[
  2067     "
  1802         r := r * (10.0 raisedToInteger:300).
  2068      (QDouble fromFloat:1.2345) printOn:Transcript
  1803         r := r / (10.0 raisedToInteger:(e+300)).
  2069      ((QDouble fromFloat:1.2345) / 10.0) printOn:Transcript
       
  2070     "
       
  2071 
       
  2072     "Created: / 15-06-2017 / 01:51:36 / cg"
       
  2073     "Modified (comment): / 15-06-2017 / 08:50:25 / cg"
       
  2074 !
       
  2075 
       
  2076 printOn:aStream precision:precision width:width 
       
  2077     fixed:fixed showPositive:showPositive uppercase:uppercase fillChar:fillChar
       
  2078 
       
  2079     "return a printed representation of the receiver.
       
  2080      This is a parametrized entry, which can be used by printf-like functions"
       
  2081 
       
  2082     |sgn count delta exp|
       
  2083 
       
  2084     self d1 = 0.0 ifTrue:[
       
  2085         self d0 printOn:aStream.
       
  2086         ^ self.
       
  2087     ].
       
  2088 
       
  2089     count := 0.
       
  2090     sgn := true.
       
  2091     exp := 0.
       
  2092     
       
  2093     self isInfinite ifTrue:[
       
  2094         self < 0 ifTrue:[
       
  2095             aStream nextPut:$-.
       
  2096             count := 1.
       
  2097         ] ifFalse:[
       
  2098             showPositive ifTrue:[
       
  2099                 aStream nextPut:$+.
       
  2100                 count := 1.
       
  2101             ] ifFalse:[
       
  2102                 sgn := false.
       
  2103             ].    
       
  2104         ].
       
  2105         uppercase ifTrue:[
       
  2106             aStream nextPutAll:'INF'
       
  2107         ] ifFalse:[
       
  2108             aStream nextPutAll:'inf'
       
  2109         ].
       
  2110         count := count + 3.
  1804     ] ifFalse:[
  2111     ] ifFalse:[
  1805         e > 300 ifTrue:[
  2112         self isNaN ifTrue:[
  1806         ] ifFalse:[
  2113             uppercase ifTrue:[
       
  2114                 aStream nextPutAll:'NAN'
       
  2115             ] ifFalse:[
       
  2116                 aStream nextPutAll:'nan'
       
  2117             ].
       
  2118             count := count + 3.
       
  2119         ] ifFalse:[        
       
  2120             self < 0 ifTrue:[
       
  2121                 aStream nextPut:$-.
       
  2122                 count := count + 1.
       
  2123             ] ifFalse:[
       
  2124                 showPositive ifTrue:[
       
  2125                     aStream nextPut:$+.
       
  2126                     count := count + 1.
       
  2127                 ] ifFalse:[
       
  2128                     sgn := false.
       
  2129                 ].    
       
  2130             ].
       
  2131             self = 0.0 ifTrue:[
       
  2132                 aStream nextPut:$0.
       
  2133                 count := count + 1.
       
  2134                 precision > 0 ifTrue:[
       
  2135                     aStream nextPut:$..
       
  2136                     count := count + 1.
       
  2137                     precision timesRepeat:[ aStream nextPut:$0 ].
       
  2138                     count := count + precision.
       
  2139                 ].    
       
  2140                 self halt.
       
  2141             ] ifFalse:[
       
  2142                 |off d d_width_extra|
       
  2143                 
       
  2144                 "/ non-zero case
       
  2145                 off := fixed 
       
  2146                         ifTrue:[ 1 + self abs log10 floor ]
       
  2147                         ifFalse:[1].
       
  2148                 d := precision + off.
       
  2149                 d_width_extra := d.
       
  2150                 fixed ifTrue:[
       
  2151                     d_width_extra := 120 max:d.
       
  2152                 ].    
       
  2153                 "/ highly special case - fixed mode, precision is zero, abs(*this) < 1.0
       
  2154                 "/ without this trap a number like 0.9 printed fixed with 0 precision prints as 0
       
  2155                 "/ should be rounded to 1.
       
  2156                 (fixed and:[ (precision == 0) and:[ (self abs < 1.0) ]]) ifTrue:[
       
  2157                     (self abs >= 0.5) ifTrue:[
       
  2158                         aStream nextPut:$1
       
  2159                     ] ifFalse:[
       
  2160                         aStream nextPut:$0
       
  2161                     ].
       
  2162                     ^ self
       
  2163                 ].
       
  2164                 
       
  2165                 "/ handle near zero to working precision (but not exactly zero)
       
  2166                 (fixed and:[ d <= 0 ]) ifTrue:[
       
  2167                     aStream nextPut:$0.
       
  2168                     (precision > 0) ifTrue:[
       
  2169                         aStream nextPut:$. .
       
  2170                         aStream next:precision put:$0.
       
  2171                     ]
       
  2172                 ] ifFalse:[
       
  2173                     "/ default
       
  2174 
       
  2175                     |t j|
       
  2176 
       
  2177                     fixed ifTrue:[
       
  2178                         t := String streamContents:[:s |
       
  2179                                 self 
       
  2180                                     printDigitsOn:s 
       
  2181                                     precision:d_width_extra 
       
  2182                                     exponentInto:[:e | exp := e]
       
  2183                              ].    
       
  2184                     ] ifFalse:[
       
  2185                         t := String streamContents:[:s |
       
  2186                                 self 
       
  2187                                     printDigitsOn:s 
       
  2188                                     precision:d 
       
  2189                                     exponentInto:[:e | exp := e]
       
  2190                              ].    
       
  2191                     ].
       
  2192 
       
  2193                     fixed ifTrue:[
       
  2194                         "/ fix the string if it's been computed incorrectly
       
  2195                         "/ round here in the decimal string if required
       
  2196                         t := self round_string_qd:t at:(d + 1) offsetInto:[:o | off := o].
       
  2197 
       
  2198                         (off > 0) ifTrue:[
       
  2199                             aStream next:off putAll:t startingAt:0.
       
  2200                             (precision > 0) ifTrue:[
       
  2201                                 aStream nextPut:$. .
       
  2202                                 aStream next:precision putAll:t startingAt:off+1.
       
  2203                             ]
       
  2204                         ] ifFalse:[
       
  2205                             aStream nextPutAll:'0.'.
       
  2206                             (off < 0) ifTrue:[
       
  2207                                 aStream next:off negated put:$0.
       
  2208                             ].
       
  2209                             aStream next:d putAll:t startingAt:0.
       
  2210                         ]
       
  2211                     ] ifFalse:[
       
  2212                         aStream nextPut:(t at:1).
       
  2213                         (precision > 0) ifTrue:[
       
  2214                             aStream nextPut:$. .
       
  2215                         ].
       
  2216                         aStream next:precision putAll:t startingAt:2.
       
  2217                     ]
       
  2218                 ].
       
  2219             ].
  1807         ]
  2220         ]
  1808     ].
  2221     ].
  1809     
  2222 
  1810     
  2223     "/ trap for improper offset with large values
  1811     "
  2224     "/ without this trap, output of values of the for 10^j - 1 fail for j > 28
  1812      1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |]
  2225     "/ and are output with the point in the wrong place, leading to a dramatically off value
  1813     "
  2226 
  1814 
  2227 "/    (fixed and:[ (precision > 0) ]) ifTrue:[
  1815     "Created: / 13-06-2017 / 17:28:08 / cg"
  2228 "/        "/ make sure that the value isn't dramatically larger
       
  2229 "/        from_string = atof(s.c_str());
       
  2230 "/
       
  2231 "/        // if this ratio is large, then we've got problems
       
  2232 "/        if( fabs( from_string / this->x[0] ) > 3.0 ){
       
  2233 "/
       
  2234 "/                int point_position;
       
  2235 "/                char temp;
       
  2236 "/
       
  2237 "/                // loop on the string, find the point, move it up one
       
  2238 "/                // don't act on the first character
       
  2239 "/                for(i=1; i < s.length(); i++){
       
  2240 "/                        if(s[i] == '.'){
       
  2241 "/                                s[i] = s[i-1] ;
       
  2242 "/                                s[i-1] = '.' ;
       
  2243 "/                                break;
       
  2244 "/                        }
       
  2245 "/                }
       
  2246 "/
       
  2247 "/                from_string = atof(s.c_str());
       
  2248 "/                // if this ratio is large, then the string has not been fixed
       
  2249 "/                if( fabs( from_string / this->x[0] ) > 3.0 ){
       
  2250 "/                        dd_real::error("Re-rounding unsuccessful in large number fixed point trap.") ;
       
  2251 "/                }
       
  2252 "/        }
       
  2253 "/    }
       
  2254 "/
       
  2255 "/    if (!!fixed) {
       
  2256 "/      /* Fill in exponent part */
       
  2257 "/      s += uppercase ? 'E' : 'e';
       
  2258 "/      append_expn(s, e);
       
  2259 "/    }
       
  2260 "/  }
       
  2261 
       
  2262     "/ fill in the blanks
       
  2263     (delta := width-count) > 0 ifTrue:[
       
  2264         self halt.
       
  2265 "/    if (fmt & ios_base::internal) {
       
  2266 "/      if (sgn)
       
  2267 "/        s.insert(static_cast<string::size_type>(1), delta, fill);
       
  2268 "/      else
       
  2269 "/        s.insert(static_cast<string::size_type>(0), delta, fill);
       
  2270 "/    } else if (fmt & ios_base::left) {
       
  2271 "/      s.append(delta, fill);
       
  2272 "/    } else {
       
  2273 "/      s.insert(static_cast<string::size_type>(0), delta, fill);
       
  2274 "/    }
       
  2275 "/  }
       
  2276     ].
       
  2277 
       
  2278     "Created: / 15-06-2017 / 02:37:31 / cg"
  1816 !
  2279 !
  1817 
  2280 
  1818 printString
  2281 printString
  1819     "return a printed representation of the receiver"
  2282     "return a printed representation of the receiver"
  1820 
  2283 
  1821     self d1 = 0.0 ifTrue:[
  2284     ^ String streamContents:[:s | self printOn:s]
  1822         ^ self d0 printString
       
  1823     ].
       
  1824     ^ self d0 printString , '...'
       
  1825 
  2285 
  1826     "Created: / 12-06-2017 / 23:41:04 / cg"
  2286     "Created: / 12-06-2017 / 23:41:04 / cg"
       
  2287     "Modified: / 15-06-2017 / 01:53:46 / cg"
  1827 ! !
  2288 ! !
  1828 
  2289 
  1829 !QDouble methodsFor:'private accessing'!
  2290 !QDouble methodsFor:'private accessing'!
  1830 
  2291 
  1831 d0
  2292 d0
  1865     "Created: / 12-06-2017 / 20:15:32 / cg"
  2326     "Created: / 12-06-2017 / 20:15:32 / cg"
  1866     "Modified (comment): / 13-06-2017 / 18:00:18 / cg"
  2327     "Modified (comment): / 13-06-2017 / 18:00:18 / cg"
  1867 !
  2328 !
  1868 
  2329 
  1869 renorm
  2330 renorm
       
  2331     "destructive renormalization"
  1870 %{
  2332 %{
  1871     double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; 
  2333     double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; 
  1872     double c0, c1, c2, c3;
  2334     double c0, c1, c2, c3;
  1873     OBJ newQD;
       
  1874 
  2335 
  1875     c0 = a[0];
  2336     c0 = a[0];
  1876     c1 = a[1];
  2337     c1 = a[1];
  1877     c2 = a[2];
  2338     c2 = a[2];
  1878     c3 = a[3];
  2339     c3 = a[3];
  1888     "
  2349     "
  1889      (QDouble fromFloat:1.0) renorm
  2350      (QDouble fromFloat:1.0) renorm
  1890     "
  2351     "
  1891 
  2352 
  1892     "Created: / 13-06-2017 / 18:05:33 / cg"
  2353     "Created: / 13-06-2017 / 18:05:33 / cg"
       
  2354     "Modified: / 15-06-2017 / 00:12:59 / cg"
       
  2355 ! !
       
  2356 
       
  2357 !QDouble methodsFor:'testing'!
       
  2358 
       
  2359 isInfinite
       
  2360     ^ self d0 isInfinite
       
  2361 
       
  2362     "Created: / 15-06-2017 / 01:57:57 / cg"
       
  2363 !
       
  2364 
       
  2365 isNaN
       
  2366     ^ self d0 isNaN
       
  2367 
       
  2368     "Created: / 15-06-2017 / 01:57:35 / cg"
  1893 ! !
  2369 ! !
  1894 
  2370 
  1895 !QDouble class methodsFor:'documentation'!
  2371 !QDouble class methodsFor:'documentation'!
  1896 
  2372 
  1897 version
  2373 version