diff options
-rw-r--r-- | Include/floatobject.h | 4 | ||||
-rw-r--r-- | Lib/test/floating_points.txt | 1021 | ||||
-rw-r--r-- | Lib/test/test_float.py | 17 | ||||
-rw-r--r-- | Makefile.pre.in | 1 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Objects/doubledigits.c | 601 | ||||
-rw-r--r-- | Objects/floatobject.c | 108 | ||||
-rw-r--r-- | PCbuild/pythoncore.vcproj | 3 | ||||
-rw-r--r-- | PCbuild8/pythoncore/pythoncore.vcproj | 4 | ||||
-rw-r--r-- | PCbuild9/pythoncore.vcproj | 4 |
10 files changed, 1764 insertions, 3 deletions
diff --git a/Include/floatobject.h b/Include/floatobject.h index be1a80c..85537f1 100644 --- a/Include/floatobject.h +++ b/Include/floatobject.h @@ -86,6 +86,10 @@ PyAPI_FUNC(void) PyFloat_AsString(char*, PyFloatObject *v); PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le); PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le); +/* Used to get the important decimal digits of a double */ +PyAPI_FUNC(int) _PyFloat_Digits(char *buf, double v, int *signum); +PyAPI_FUNC(void) _PyFloat_DigitsInit(void); + /* The unpack routines read 4 or 8 bytes, starting at p. le is a bool * argument, true if the string is in little-endian format (exponent * last, at p+3 or p+7), false if big-endian (exponent first, at p). diff --git a/Lib/test/floating_points.txt b/Lib/test/floating_points.txt new file mode 100644 index 0000000..70d21ea --- /dev/null +++ b/Lib/test/floating_points.txt @@ -0,0 +1,1021 @@ +# These numbers are used to test floating point binary-to-decimal conversion. +# They are based on the TCL test suite (tests/expr.test), which is based on +# test data from: +# Brigitte Verdonk, Annie Cuyt, Dennis Verschaeren, A precision and range +# independent tool for testing floating-point arithmetic II: Conversions, +# ACM Transactions on Mathematical Software 27:2 (March 2001), pp. 119-140. + +0E0 +-0E0 +1E0 +15E-1 +125E-2 +1125E-3 +10625E-4 +103125E-5 +1015625E-6 +10078125E-7 +100390625E-8 +1001953125E-9 +10009765625E-10 +100048828125E-11 +1000244140625E-12 +10001220703125E-13 +100006103515625E-14 +1000030517578125E-15 +10000152587890625E-16 ++8E153 +-1E153 ++9E306 +-2E153 ++7E-304 +-3E-49 ++7E-303 +-6E-49 ++9E43 +-9E44 ++8E303 +-1E303 ++7E-287 +-2E-204 ++2E-205 +-9E-47 ++34E195 +-68E195 ++85E194 +-67E97 ++93E-234 +-19E-87 ++38E-87 +-38E-88 +-69E220 ++18E43 +-36E43 ++61E-99 +-43E-92 ++86E-92 +-51E-74 ++283E85 +-566E85 ++589E187 +-839E143 +-744E-234 ++930E-235 +-186E-234 ++604E175 +-302E175 ++755E174 +-151E175 ++662E-213 +-408E-74 ++510E-75 ++6782E55 +-2309E92 ++7963E34 +-3391E55 ++7903E-96 +-7611E-226 ++4907E-196 +-5547E-311 ++5311E241 +-5311E243 ++5311E242 ++9269E-45 +-8559E-289 ++8699E-276 +-8085E-64 ++74819E201 +-82081E41 ++51881E37 +-55061E157 ++77402E-215 +-33891E-92 ++38701E-215 +-82139E-76 ++75859E25 ++89509E140 +-57533E287 ++46073E-32 +-92146E-32 ++83771E-74 +-34796E-276 ++584169E229 ++164162E41 +-328324E41 ++209901E-11 +-419802E-11 ++940189E-112 +-892771E-213 ++757803E120 +-252601E120 ++252601E121 +-505202E120 ++970811E-264 +-654839E-60 ++289767E-178 +-579534E-178 +-8823691E130 ++9346704E229 +-1168338E229 +-6063369E-136 ++3865421E-225 +-5783893E-127 ++2572231E223 +-5144462E223 ++1817623E109 ++6431543E-97 +-5444097E-21 ++8076999E-121 +-9997649E-270 ++50609263E157 ++70589528E130 +-88236910E129 ++87575437E-310 +-23135572E-127 ++85900881E177 +-84863171E113 ++68761586E232 +-50464069E286 ++27869147E-248 +-55738294E-248 ++70176353E-53 +-80555086E-32 +-491080654E121 ++526250918E287 +-245540327E121 +-175150874E-310 ++350301748E-310 +-437877185E-311 ++458117166E52 +-916234332E52 ++229058583E52 +-525789935E98 ++282926897E-227 +-565853794E-227 ++667284113E-240 +-971212611E-126 ++9981396317E-182 +-5035231965E-156 ++8336960483E-153 +-8056371144E-155 ++6418488827E79 +-3981006983E252 ++7962013966E252 +-4713898551E261 ++8715380633E-58 +-9078555839E-109 ++9712126110E-127 ++42333842451E201 +-84667684902E201 ++23792120709E-315 +-78564021519E-227 ++71812054883E-188 +-30311163631E-116 ++71803914657E292 ++36314223356E-109 ++18157111678E-109 +-45392779195E-110 ++778380362293E218 +-685763015669E280 ++952918668151E70 +-548357443505E32 ++384865004907E-285 +-769730009814E-285 ++697015418417E-93 +-915654049301E-28 ++178548656339E169 +-742522891517E259 ++742522891517E258 +-357097312678E169 +-3113521449172E218 ++3891901811465E217 +-1556760724586E218 ++9997878507563E-195 +-7247563029154E-319 ++3623781514577E-319 +-3092446298323E-200 ++6363857920591E145 +-8233559360849E94 ++2689845954547E49 +-5379691909094E49 ++5560322501926E-301 +-7812878489261E-179 ++8439398533053E-256 +-2780161250963E-301 +-87605699161665E155 +-17521139832333E156 +-88218101363513E-170 ++38639244311627E-115 ++35593959807306E261 +-53390939710959E260 ++71187919614612E261 +-88984899518265E260 ++77003665618895E-73 +-15400733123779E-72 ++61602932495116E-72 +-30801466247558E-72 ++834735494917063E-300 +-589795149206434E-151 ++475603213226859E-42 +-294897574603217E-151 ++850813008001913E93 +-203449172043339E185 ++406898344086678E185 +-813796688173356E185 ++6045338514609393E244 +-5145963778954906E142 ++2572981889477453E142 +-6965949469487146E74 ++6182410494241627E-119 +-8510309498186985E-277 ++6647704637273331E-212 +-2215901545757777E-212 ++3771476185376383E276 +-3729901848043846E212 ++3771476185376383E277 +-9977830465649166E119 ++8439928496349319E-142 +-8204230082070882E-59 ++8853686434843997E-244 +-5553274272288559E-104 ++36149023611096162E144 +-36149023611096162E147 ++18074511805548081E146 +-18074511805548081E147 ++97338774138954421E-290 +-88133809804950961E-308 ++94080055902682397E-243 +-24691002732654881E-115 ++52306490527514614E49 +-26153245263757307E49 ++55188692254193604E165 +-68985865317742005E164 ++27176258005319167E-261 +-73169230107256116E-248 ++91461537634070145E-249 +-54352516010638334E-261 ++586144289638535878E280 +-601117006785295431E245 ++293072144819267939E280 +-953184713238516652E272 ++902042358290366539E-281 +-557035730189854663E-294 ++902042358290366539E-280 +-354944100507554393E-238 ++272104041512242479E199 +-816312124536727437E199 ++544208083024484958E199 +-792644927852378159E78 +-679406450132979175E-263 ++543525160106383340E-262 ++7400253695682920196E215 +-1850063423920730049E215 ++3700126847841460098E215 +-9250317119603650245E214 ++8396094300569779681E-252 +-3507665085003296281E-75 ++7015330170006592562E-75 +-7015330170006592562E-74 ++7185620434951919351E205 +-1360520207561212395E198 ++2178999185345151731E-184 +-8691089486201567102E-218 ++4345544743100783551E-218 +-4357998370690303462E-184 ++59825267349106892461E177 +-62259110684423957791E47 ++58380168477038565599E265 +-62259110684423957791E48 +-33584377202279118724E-252 +-57484963479615354808E205 ++71856204349519193510E204 +-14371240869903838702E205 ++36992084760177624177E-318 +-73984169520355248354E-318 ++99257763227713890244E-115 +-87336362425182547697E-280 ++7E289 +-3E153 ++6E153 +-5E243 ++7E-161 +-7E-172 ++8E-63 +-7E-113 ++8E126 +-4E126 ++5E125 +-1E126 ++8E-163 +-1E-163 ++2E-163 +-4E-163 ++51E195 +-37E46 ++74E46 +-56E289 ++69E-145 +-70E-162 ++56E-161 +-21E-303 ++34E-276 +-68E-276 ++85E-277 +-87E-274 ++829E102 +-623E100 ++723E-162 +-457E-102 ++914E-102 +-323E-135 ++151E176 +-302E176 ++921E90 +-604E176 ++823E-206 +-463E-114 ++348E-274 ++9968E100 +-6230E99 ++1246E100 ++6676E-296 +-8345E-297 ++1669E-296 +-3338E-296 ++3257E58 +-6514E58 ++2416E176 ++8085E-63 +-3234E-62 ++1617E-62 +-6468E-62 ++53418E111 +-60513E160 ++26709E111 +-99447E166 ++12549E48 +-25098E48 ++50196E48 +-62745E47 ++83771E-73 +-97451E-167 ++86637E-203 +-75569E-254 ++473806E83 +-947612E83 ++292369E76 +-584738E76 ++933587E-140 +-720919E-14 ++535001E-149 +-890521E-235 ++548057E81 +-706181E88 ++820997E106 +-320681E63 ++928609E-261 +-302276E-254 ++151138E-254 ++4691773E45 +-9383546E45 ++3059949E-243 +-6119898E-243 ++5356626E-213 +-4877378E-199 ++7716693E223 +-5452869E109 ++4590831E156 +-9181662E156 +-3714436E-261 ++4643045E-262 +-7428872E-261 ++52942146E130 +-27966061E145 ++26471073E130 +-55932122E145 ++95412548E-99 +-47706274E-99 ++23853137E-99 +-78493654E-301 ++65346417E29 +-51083099E167 ++89396333E264 +-84863171E114 ++59540836E-251 +-74426045E-252 ++14885209E-251 +-29770418E-251 ++982161308E122 +-245540327E122 ++491080654E122 ++525452622E-310 +-771837113E-134 ++820858081E-150 +-262726311E-310 ++923091487E209 +-653777767E273 ++842116236E-53 +-741111169E-202 ++839507247E-284 +-951487269E-264 +-9821613080E121 ++6677856011E-31 +-3573796826E-266 ++7147593652E-266 +-9981396317E-181 ++3268888835E272 +-2615111068E273 ++1307555534E273 ++2990671154E-190 +-1495335577E-190 ++5981342308E-190 +-7476677885E-191 ++82259684194E-202 +-93227267727E-49 ++41129842097E-202 +-47584241418E-314 +-79360293406E92 ++57332259349E225 +-57202326162E111 ++86860597053E-206 +-53827010643E-200 ++53587107423E-61 ++635007636765E200 ++508006109412E201 +-254003054706E201 ++561029718715E-72 +-897647549944E-71 ++112205943743E-71 +-873947086081E-236 ++809184709177E116 +-573112917422E81 ++286556458711E81 ++952805821491E-259 +-132189992873E-44 +-173696038493E-144 ++1831132757599E-107 +-9155663787995E-108 ++7324531030396E-107 +-9277338894969E-200 ++8188292423973E287 +-5672557437938E59 ++2836278718969E59 +-9995153153494E54 ++9224786422069E-291 +-3142213164987E-294 ++6284426329974E-294 +-8340483752889E-301 ++67039371486466E89 +-62150786615239E197 ++33519685743233E89 +-52563419496999E156 ++32599460466991E-65 +-41010988798007E-133 ++65198920933982E-65 +-82021977596014E-133 ++80527976643809E61 +-74712611505209E158 ++53390939710959E261 +-69277302659155E225 ++46202199371337E-72 +-23438635467783E-179 ++41921560615349E-67 +-92404398742674E-72 ++738545606647197E124 +-972708181182949E117 +-837992143580825E87 ++609610927149051E-255 +-475603213226859E-41 ++563002800671023E-177 +-951206426453718E-41 ++805416432656519E202 +-530658674694337E159 ++946574173863918E208 +-318329953318553E113 +-462021993713370E-73 ++369617594970696E-72 ++3666156212014994E233 +-1833078106007497E233 ++8301790508624232E174 +-1037723813578029E174 ++7297662880581139E-286 +-5106185698912191E-276 ++7487252720986826E-165 +-3743626360493413E-165 ++3773057430100257E230 +-7546114860200514E230 ++4321222892463822E58 +-7793560217139653E51 ++26525993941010681E112 +-53051987882021362E112 ++72844871414247907E77 +-88839359596763261E105 ++18718131802467065E-166 +-14974505441973652E-165 ++73429396004640239E106 +-58483921078398283E57 ++41391519190645203E165 +-82783038381290406E165 ++58767043776702677E-163 +-90506231831231999E-129 ++64409240769861689E-159 +-77305427432277771E-190 ++476592356619258326E273 +-953184713238516652E273 ++899810892172646163E283 +-929167076892018333E187 ++647761278967534239E-312 +-644290479820542942E-180 ++926145344610700019E-225 +-958507931896511964E-246 ++272104041512242479E200 +-792644927852378159E79 ++544208083024484958E200 +-929963218616126365E290 ++305574339166810102E-219 +-152787169583405051E-219 ++611148678333620204E-219 +-763935847917025255E-220 ++7439550220920798612E158 +-3719775110460399306E158 ++9299437776150998265E157 +-7120190517612959703E120 ++3507665085003296281E-73 +-7015330170006592562E-73 +-6684428762278255956E-294 +-1088416166048969916E200 +-8707329328391759328E200 ++4439021781608558002E-65 +-8878043563217116004E-65 ++2219510890804279001E-65 ++33051223951904955802E55 +-56961524140903677624E120 ++71201905176129597030E119 ++14030660340013185124E-73 +-17538325425016481405E-74 ++67536228609141569109E-133 +-35620497849450218807E-306 ++66550376797582521751E-126 +-71240995698900437614E-306 ++3E24 +-6E24 ++6E26 +-7E25 ++1E-14 +-2E-14 ++4E-14 +-8E-14 ++5E26 +-8E27 ++1E27 +-4E27 ++9E-13 +-7E-20 ++56E25 +-70E24 ++51E26 ++71E-17 +-31E-5 ++62E-5 +-94E-8 ++67E27 +-81E24 ++54E23 +-54E25 ++63E-22 +-63E-23 ++43E-4 +-86E-4 ++942E26 +-471E25 ++803E24 +-471E26 +-409E-21 ++818E-21 +-867E-8 ++538E27 +-857E24 ++269E27 +-403E26 ++959E-7 +-959E-6 ++373E-27 +-746E-27 ++4069E24 +-4069E23 +-8138E24 ++8294E-15 +-4147E-14 ++4147E-15 +-8294E-14 ++538E27 +-2690E26 ++269E27 +-2152E27 ++1721E-17 +-7979E-27 ++6884E-17 +-8605E-18 ++82854E27 +-55684E24 ++27842E24 +-48959E25 ++81921E-17 +-76207E-8 ++4147E-15 +-41470E-16 ++89309E24 ++75859E26 +-75859E25 ++14257E-23 +-28514E-23 ++57028E-23 +-71285E-24 ++344863E27 +-951735E27 ++200677E23 +-401354E24 ++839604E-11 +-209901E-11 ++419802E-11 +-537734E-24 ++910308E26 +-227577E26 ++455154E26 +-531013E25 ++963019E-21 +-519827E-13 ++623402E-27 +-311701E-27 ++9613651E26 +-9191316E23 ++4595658E23 +-2297829E23 +-1679208E-11 ++3379223E27 +-6758446E27 ++5444097E-21 +-8399969E-27 ++8366487E-16 +-8366487E-15 ++65060671E25 ++65212389E23 ++55544957E-13 +-51040905E-20 ++99585767E-22 +-99585767E-23 ++40978393E26 +-67488159E24 ++69005339E23 +-81956786E26 +-87105552E-21 ++10888194E-21 +-21776388E-21 ++635806667E27 +-670026614E25 ++335013307E26 +-335013307E25 ++371790617E-24 +-371790617E-25 ++743581234E-24 +-743581234E-25 ++202464477E24 +-404928954E24 ++997853758E27 +-997853758E26 ++405498418E-17 +-582579084E-14 ++608247627E-18 +-291289542E-14 +-9537100005E26 ++6358066670E27 +-1271613334E27 ++5229646999E-16 ++5229646999E-17 ++4429943614E24 +-8859887228E24 ++2214971807E24 +-4176887093E26 ++4003495257E-20 +-4361901637E-23 ++8723803274E-23 +-8006990514E-20 ++72835110098E27 +-36417555049E27 ++84279630104E25 +-84279630104E24 ++21206176437E-27 +-66461566917E-22 ++64808355539E-16 +-84932679673E-19 ++65205430094E26 +-68384463429E25 ++32602715047E26 +-62662203426E27 ++58784444678E-18 +-50980203373E-21 ++29392222339E-18 +-75529940323E-27 +-937495906299E26 ++842642485799E-20 +-387824150699E-23 ++924948814726E-27 +-775648301398E-23 ++547075707432E25 ++683844634290E24 +-136768926858E25 ++509802033730E-22 ++101960406746E-21 +-815683253968E-21 ++7344124123524E24 +-9180155154405E23 ++6479463327323E27 +-1836031030881E24 ++4337269293039E-19 +-4599163554373E-23 ++9198327108746E-23 ++4812803938347E27 +-8412030890011E23 ++9625607876694E27 +-4739968828249E24 ++9697183891673E-23 +-7368108517543E-20 ++51461358161422E25 +-77192037242133E26 ++77192037242133E25 +-51461358161422E27 ++43999661561541E-21 +-87999323123082E-21 ++48374886826137E-26 +-57684246567111E-23 ++87192805957686E23 +-75108713005913E24 ++64233110587487E27 +-77577471133384E-23 ++48485919458365E-24 +-56908598265713E-26 ++589722294620133E23 ++652835804449289E-22 +-656415363936202E-23 ++579336749585745E-25 +-381292764980839E-26 ++965265859649698E23 +-848925235434882E27 ++536177612222491E23 +-424462617717441E27 ++276009279888989E-27 +-608927158043691E-26 ++552018559777978E-27 +-425678377667758E-22 ++8013702726927119E26 ++8862627962362001E27 +-5068007907757162E26 +-7379714799828406E-23 ++4114538064016107E-27 +-3689857399914203E-23 ++5575954851815478E23 ++3395700941739528E27 ++4115535777581961E-23 +-8231071555163922E-23 ++6550246696190871E-26 +-68083046403986701E27 ++43566388595783643E27 +-87132777191567286E27 ++59644881059342141E25 +-83852770718576667E23 ++99482967418206961E-25 +-99482967418206961E-26 ++87446669969994614E-27 +-43723334984997307E-27 ++5E24 +-8E25 ++1E25 +-4E25 ++2E-5 +-5E-6 ++4E-5 +-3E-20 ++3E27 +-9E26 ++7E25 +-6E27 ++2E-21 +-5E-22 +-4E-21 ++87E25 +-97E24 ++82E-24 +-41E-24 ++76E-23 ++83E25 +-50E27 ++25E27 +-99E27 ++97E-10 +-57E-20 ++997E23 ++776E24 +-388E24 ++521E-10 +-506E-26 ++739E-10 +-867E-7 +-415E24 ++332E25 +-664E25 ++291E-13 +-982E-8 ++582E-13 +-491E-8 ++4574E26 +-8609E26 ++2287E26 +-4818E24 ++6529E-8 +-8151E-21 ++1557E-12 +-2573E-18 ++4929E-16 +-3053E-22 ++9858E-16 +-7767E-11 ++54339E26 +-62409E25 ++32819E27 +-89849E27 ++63876E-20 +-15969E-20 ++31938E-20 +-79845E-21 ++89306E27 +-25487E24 ++79889E24 +-97379E26 ++81002E-8 +-43149E-25 ++40501E-8 +-60318E-10 +-648299E27 ++780649E24 ++720919E-14 +-629703E-11 ++557913E24 +-847899E23 ++565445E27 +-736531E24 ++680013E-19 +-529981E-10 ++382923E-23 +-633614E-18 ++2165479E27 +-8661916E27 ++4330958E27 +-9391993E22 +-5767352E-14 ++7209190E-15 +-1441838E-14 ++8478990E22 ++1473062E24 ++8366487E-14 +-8399969E-25 ++9366737E-12 +-9406141E-13 ++65970979E24 +-65060671E26 ++54923002E27 +-63846927E25 ++99585767E-21 ++67488159E25 +-69005339E24 ++81956786E27 +-40978393E27 ++77505754E-12 +-38752877E-12 ++82772981E-15 +-95593517E-25 ++200036989E25 +-772686455E27 ++859139907E23 +-400073978E25 ++569014327E-14 +-794263862E-15 ++397131931E-15 +-380398957E-16 ++567366773E27 +-337440795E24 ++134976318E25 +-269952636E25 ++932080597E-20 +-331091924E-15 +-413864905E-16 ++8539246247E26 +-5859139791E26 ++6105010149E24 +-3090745820E27 ++3470877773E-20 +-6136309089E-27 ++8917758713E-19 +-6941755546E-20 ++9194900535E25 +-1838980107E26 ++7355920428E26 +-3677960214E26 ++8473634343E-17 +-8870766274E-16 ++4435383137E-16 +-9598990129E-15 ++71563496764E26 +-89454370955E25 ++17890874191E26 +-35781748382E26 ++57973447842E-19 +-28986723921E-19 ++76822711313E-19 +-97699466874E-20 ++67748656762E27 +-19394840991E24 ++38789681982E24 +-33874328381E27 ++54323763886E-27 +-58987193887E-20 ++27161881943E-27 +-93042648033E-19 ++520831059055E27 +-768124264394E25 ++384062132197E25 ++765337749889E-25 ++794368912771E25 +-994162090146E23 ++781652779431E26 ++910077190046E-26 +-455038595023E-26 ++471897551096E-20 +-906698409911E-21 ++8854128003935E25 +-8146122716299E27 ++7083302403148E26 +-3541651201574E26 ++8394920649291E-25 +-7657975756753E-22 ++5473834002228E-20 +-6842292502785E-21 +-2109568884597E25 ++8438275538388E25 +-4219137769194E25 ++3200141789841E-25 +-8655689322607E-22 ++6400283579682E-25 +-8837719634493E-21 ++19428217075297E24 +-38856434150594E24 ++77712868301188E24 +-77192037242133E27 ++76579757567530E-23 ++15315951513506E-22 +-38289878783765E-23 ++49378033925202E25 +-50940527102367E24 ++98756067850404E25 +-99589397544892E26 +-56908598265713E-25 ++97470695699657E-22 +-35851901247343E-25 ++154384074484266E27 +-308768148968532E27 ++910990389005985E23 ++271742424169201E-27 +-543484848338402E-27 ++162192083357563E-26 +-869254552770081E-23 ++664831007626046E24 +-332415503813023E24 ++943701829041427E24 +-101881054204734E24 ++828027839666967E-27 +-280276135608777E-27 ++212839188833879E-21 +-113817196531426E-25 ++9711553197796883E27 +-2739849386524269E26 ++5479698773048538E26 ++6124568318523113E-25 +-1139777988171071E-24 ++6322612303128019E-27 +-2955864564844617E-25 +-9994029144998961E25 +-2971238324022087E27 +-1656055679333934E-27 +-1445488709150234E-26 ++55824717499885172E27 +-69780896874856465E26 ++84161538867545199E25 +-27912358749942586E27 ++24711112462926331E-25 +-12645224606256038E-27 +-12249136637046226E-25 ++74874448287465757E27 +-35642836832753303E24 +-71285673665506606E24 ++43723334984997307E-26 ++10182419849537963E-24 +-93501703572661982E-26 diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 1c74c96..327eeae 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -1,5 +1,6 @@ import unittest, struct +import os from test import test_support class FormatFunctionsTestCase(unittest.TestCase): @@ -115,11 +116,25 @@ class IEEEFormatTestCase(unittest.TestCase): self.assertEquals(pos_neg(), neg_neg()) +class ReprTestCase(unittest.TestCase): + def test_repr(self): + floats_file = open(os.path.join(os.path.split(__file__)[0], + 'floating_points.txt')) + for line in floats_file: + line = line.strip() + if not line or line.startswith('#'): + continue + v = eval(line) + self.assertEqual(v, eval(repr(v))) + floats_file.close() + + def test_main(): test_support.run_unittest( FormatFunctionsTestCase, UnknownFormatTestCase, - IEEEFormatTestCase) + IEEEFormatTestCase, + ReprTestCase) if __name__ == '__main__': test_main() diff --git a/Makefile.pre.in b/Makefile.pre.in index 70e5b0e..c2a061a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -299,6 +299,7 @@ OBJECT_OBJS= \ Objects/genobject.o \ Objects/fileobject.o \ Objects/floatobject.o \ + Objects/doubledigits.o \ Objects/frameobject.o \ Objects/funcobject.o \ Objects/intobject.o \ @@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- +- Issue #1580: New free format floating point representation based on + "Floating-Point Printer Sample Code", by Robert G. Burger. For example + repr(11./5) now returns '2.2' instead of '2.2000000000000002'. + - Issue #1538: Avoid copying string in split/rsplit if the split char is not found. diff --git a/Objects/doubledigits.c b/Objects/doubledigits.c new file mode 100644 index 0000000..1f1c91c --- /dev/null +++ b/Objects/doubledigits.c @@ -0,0 +1,601 @@ +/* Free-format floating point printer + * + * Based on "Floating-Point Printer Sample Code", by Robert G. Burger, + * http://www.cs.indiana.edu/~burger/fp/index.html + */ + +#include "Python.h" + +#if defined(__alpha) || defined(__i386) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) +#define LITTLE_ENDIAN_IEEE_DOUBLE +#elif !(defined(__ppc__) || defined(sparc) || defined(__sgi) || defined(_IBMR2) || defined(hpux)) +#error unknown machine type +#endif + +#if defined(_M_IX86) +#define UNSIGNED64 unsigned __int64 +#elif defined(__alpha) +#define UNSIGNED64 unsigned long +#else +#define UNSIGNED64 unsigned long long +#endif + +#ifndef U32 +#define U32 unsigned int +#endif + +/* exponent stored + 1024, hidden bit to left of decimal point */ +#define bias 1023 +#define bitstoright 52 +#define m1mask 0xf +#define hidden_bit 0x100000 +#ifdef LITTLE_ENDIAN_IEEE_DOUBLE +struct dblflt { + unsigned int m4: 16; + unsigned int m3: 16; + unsigned int m2: 16; + unsigned int m1: 4; + unsigned int e: 11; + unsigned int s: 1; +}; +#else +/* Big Endian IEEE Double Floats */ +struct dblflt { + unsigned int s: 1; + unsigned int e: 11; + unsigned int m1: 4; + unsigned int m2: 16; + unsigned int m3: 16; + unsigned int m4: 16; +}; +#endif +#define float_radix 2.147483648e9 + + +typedef UNSIGNED64 Bigit; +#define BIGSIZE 24 +#define MIN_E -1074 +#define MAX_FIVE 325 +#define B_P1 ((Bigit)1 << 52) + +typedef struct { + int l; + Bigit d[BIGSIZE]; +} Bignum; + +static Bignum R, S, MP, MM, five[MAX_FIVE]; +static Bignum S2, S3, S4, S5, S6, S7, S8, S9; +static int ruf, k, s_n, use_mp, qr_shift, sl, slr; + +static void mul10(Bignum *x); +static void big_short_mul(Bignum *x, Bigit y, Bignum *z); +/* +static void print_big(Bignum *x); +*/ +static int estimate(int n); +static void one_shift_left(int y, Bignum *z); +static void short_shift_left(Bigit x, int y, Bignum *z); +static void big_shift_left(Bignum *x, int y, Bignum *z); +static int big_comp(Bignum *x, Bignum *y); +static int sub_big(Bignum *x, Bignum *y, Bignum *z); +static void add_big(Bignum *x, Bignum *y, Bignum *z); +static int add_cmp(void); +static int qr(void); + +/*static int _PyFloat_Digits(char *buf, double v, int *signum);*/ +/*static void _PyFloat_DigitsInit(void);*/ + +#define ADD(x, y, z, k) {\ + Bigit x_add, z_add;\ + x_add = (x);\ + if ((k))\ + z_add = x_add + (y) + 1, (k) = (z_add <= x_add);\ + else\ + z_add = x_add + (y), (k) = (z_add < x_add);\ + (z) = z_add;\ +} + +#define SUB(x, y, z, b) {\ + Bigit x_sub, y_sub;\ + x_sub = (x); y_sub = (y);\ + if ((b))\ + (z) = x_sub - y_sub - 1, b = (y_sub >= x_sub);\ + else\ + (z) = x_sub - y_sub, b = (y_sub > x_sub);\ +} + +#define MUL(x, y, z, k) {\ + Bigit x_mul, low, high;\ + x_mul = (x);\ + low = (x_mul & 0xffffffff) * (y) + (k);\ + high = (x_mul >> 32) * (y) + (low >> 32);\ + (k) = high >> 32;\ + (z) = (low & 0xffffffff) | (high << 32);\ +} + +#define SLL(x, y, z, k) {\ + Bigit x_sll = (x);\ + (z) = (x_sll << (y)) | (k);\ + (k) = x_sll >> (64 - (y));\ +} + +static void +mul10(Bignum *x) +{ + int i, l; + Bigit *p, k; + + l = x->l; + for (i = l, p = &x->d[0], k = 0; i >= 0; i--) + MUL(*p, 10, *p++, k); + if (k != 0) + *p = k, x->l = l+1; +} + +static void +big_short_mul(Bignum *x, Bigit y, Bignum *z) +{ + int i, xl, zl; + Bigit *xp, *zp, k; + U32 high, low; + + xl = x->l; + xp = &x->d[0]; + zl = xl; + zp = &z->d[0]; + high = y >> 32; + low = y & 0xffffffff; + for (i = xl, k = 0; i >= 0; i--, xp++, zp++) { + Bigit xlow, xhigh, z0, t, c, z1; + xlow = *xp & 0xffffffff; + xhigh = *xp >> 32; + z0 = (xlow * low) + k; /* Cout is (z0 < k) */ + t = xhigh * low; + z1 = (xlow * high) + t; + c = (z1 < t); + t = z0 >> 32; + z1 += t; + c += (z1 < t); + *zp = (z1 << 32) | (z0 & 0xffffffff); + k = (xhigh * high) + (c << 32) + (z1 >> 32) + (z0 < k); + } + if (k != 0) + *zp = k, zl++; + z->l = zl; +} + +/* +static void +print_big(Bignum *x) +{ + int i; + Bigit *p; + + printf("#x"); + i = x->l; + p = &x->d[i]; + for (p = &x->d[i]; i >= 0; i--) { + Bigit b = *p--; + printf("%08x%08x", (int)(b >> 32), (int)(b & 0xffffffff)); + } +} +*/ + +static int +estimate(int n) +{ + if (n < 0) + return (int)(n*0.3010299956639812); + else + return 1+(int)(n*0.3010299956639811); +} + +static void +one_shift_left(int y, Bignum *z) +{ + int n, m, i; + Bigit *zp; + + n = y / 64; + m = y % 64; + zp = &z->d[0]; + for (i = n; i > 0; i--) *zp++ = 0; + *zp = (Bigit)1 << m; + z->l = n; +} + +static void +short_shift_left(Bigit x, int y, Bignum *z) +{ + int n, m, i, zl; + Bigit *zp; + + n = y / 64; + m = y % 64; + zl = n; + zp = &(z->d[0]); + for (i = n; i > 0; i--) *zp++ = 0; + if (m == 0) + *zp = x; + else { + Bigit high = x >> (64 - m); + *zp = x << m; + if (high != 0) + *++zp = high, zl++; + } + z->l = zl; +} + +static void +big_shift_left(Bignum *x, int y, Bignum *z) +{ + int n, m, i, xl, zl; + Bigit *xp, *zp, k; + + n = y / 64; + m = y % 64; + xl = x->l; + xp = &(x->d[0]); + zl = xl + n; + zp = &(z->d[0]); + for (i = n; i > 0; i--) *zp++ = 0; + if (m == 0) + for (i = xl; i >= 0; i--) *zp++ = *xp++; + else { + for (i = xl, k = 0; i >= 0; i--) + SLL(*xp++, m, *zp++, k); + if (k != 0) + *zp = k, zl++; + } + z->l = zl; +} + + +static int +big_comp(Bignum *x, Bignum *y) +{ + int i, xl, yl; + Bigit *xp, *yp; + + xl = x->l; + yl = y->l; + if (xl > yl) return 1; + if (xl < yl) return -1; + xp = &x->d[xl]; + yp = &y->d[xl]; + for (i = xl; i >= 0; i--, xp--, yp--) { + Bigit a = *xp; + Bigit b = *yp; + + if (a > b) return 1; + else if (a < b) return -1; + } + return 0; +} + +static int +sub_big(Bignum *x, Bignum *y, Bignum *z) +{ + int xl, yl, zl, b, i; + Bigit *xp, *yp, *zp; + + xl = x->l; + yl = y->l; + if (yl > xl) return 1; + xp = &x->d[0]; + yp = &y->d[0]; + zp = &z->d[0]; + + for (i = yl, b = 0; i >= 0; i--) + SUB(*xp++, *yp++, *zp++, b); + for (i = xl-yl; b && i > 0; i--) { + Bigit x_sub; + x_sub = *xp++; + *zp++ = x_sub - 1; + b = (x_sub == 0); + } + for (; i > 0; i--) *zp++ = *xp++; + if (b) return 1; + zl = xl; + while (*--zp == 0) zl--; + z->l = zl; + return 0; +} + +static void +add_big(Bignum *x, Bignum *y, Bignum *z) +{ + int xl, yl, k, i; + Bigit *xp, *yp, *zp; + + xl = x->l; + yl = y->l; + if (yl > xl) { + int tl; + Bignum *tn; + tl = xl; xl = yl; yl = tl; + tn = x; x = y; y = tn; + } + + xp = &x->d[0]; + yp = &y->d[0]; + zp = &z->d[0]; + + for (i = yl, k = 0; i >= 0; i--) + ADD(*xp++, *yp++, *zp++, k); + for (i = xl-yl; k && i > 0; i--) { + Bigit z_add; + z_add = *xp++ + 1; + k = (z_add == 0); + *zp++ = z_add; + } + for (; i > 0; i--) *zp++ = *xp++; + if (k) + *zp = 1, z->l = xl+1; + else + z->l = xl; +} + +static int +add_cmp() +{ + int rl, ml, sl, suml; + static Bignum sum; + + rl = R.l; + ml = (use_mp ? MP.l : MM.l); + sl = S.l; + + suml = rl >= ml ? rl : ml; + if ((sl > suml+1) || ((sl == suml+1) && (S.d[sl] > 1))) return -1; + if (sl < suml) return 1; + + add_big(&R, (use_mp ? &MP : &MM), &sum); + return big_comp(&sum, &S); +} + +static int +qr() +{ + if (big_comp(&R, &S5) < 0) + if (big_comp(&R, &S2) < 0) + if (big_comp(&R, &S) < 0) + return 0; + else { + sub_big(&R, &S, &R); + return 1; + } + else if (big_comp(&R, &S3) < 0) { + sub_big(&R, &S2, &R); + return 2; + } + else if (big_comp(&R, &S4) < 0) { + sub_big(&R, &S3, &R); + return 3; + } + else { + sub_big(&R, &S4, &R); + return 4; + } + else if (big_comp(&R, &S7) < 0) + if (big_comp(&R, &S6) < 0) { + sub_big(&R, &S5, &R); + return 5; + } + else { + sub_big(&R, &S6, &R); + return 6; + } + else if (big_comp(&R, &S9) < 0) + if (big_comp(&R, &S8) < 0) { + sub_big(&R, &S7, &R); + return 7; + } + else { + sub_big(&R, &S8, &R); + return 8; + } + else { + sub_big(&R, &S9, &R); + return 9; + } +} + +#define OUTDIG(d) { *buf++ = (d) + '0'; *buf = 0; return k; } + +int +_PyFloat_Digits(char *buf, double v, int *signum) +{ + struct dblflt *x; + int sign, e, f_n, m_n, i, d, tc1, tc2; + Bigit f; + + /* decompose float into sign, mantissa & exponent */ + x = (struct dblflt *)&v; + sign = x->s; + e = x->e; + f = (Bigit)(x->m1 << 16 | x->m2) << 32 | (U32)(x->m3 << 16 | x->m4); + if (e != 0) { + e = e - bias - bitstoright; + f |= (Bigit)hidden_bit << 32; + } + else if (f != 0) + /* denormalized */ + e = 1 - bias - bitstoright; + + *signum = sign; + if (f == 0) { + *buf++ = '0'; + *buf = 0; + return 0; + } + + ruf = !(f & 1); /* ruf = (even? f) */ + + /* Compute the scaling factor estimate, k */ + if (e > MIN_E) + k = estimate(e+52); + else { + int n; + Bigit y; + + for (n = e+52, y = (Bigit)1 << 52; f < y; n--) y >>= 1; + k = estimate(n); + } + + if (e >= 0) + if (f != B_P1) + use_mp = 0, f_n = e+1, s_n = 1, m_n = e; + else + use_mp = 1, f_n = e+2, s_n = 2, m_n = e; + else + if ((e == MIN_E) || (f != B_P1)) + use_mp = 0, f_n = 1, s_n = 1-e, m_n = 0; + else + use_mp = 1, f_n = 2, s_n = 2-e, m_n = 0; + + /* Scale it! */ + if (k == 0) { + short_shift_left(f, f_n, &R); + one_shift_left(s_n, &S); + one_shift_left(m_n, &MM); + if (use_mp) one_shift_left(m_n+1, &MP); + qr_shift = 1; + } + else if (k > 0) { + s_n += k; + if (m_n >= s_n) + f_n -= s_n, m_n -= s_n, s_n = 0; + else + f_n -= m_n, s_n -= m_n, m_n = 0; + short_shift_left(f, f_n, &R); + big_shift_left(&five[k-1], s_n, &S); + one_shift_left(m_n, &MM); + if (use_mp) one_shift_left(m_n+1, &MP); + qr_shift = 0; + } + else { + Bignum *power = &five[-k-1]; + + s_n += k; + big_short_mul(power, f, &S); + big_shift_left(&S, f_n, &R); + one_shift_left(s_n, &S); + big_shift_left(power, m_n, &MM); + if (use_mp) big_shift_left(power, m_n+1, &MP); + qr_shift = 1; + } + + /* fixup */ + if (add_cmp() <= -ruf) { + k--; + mul10(&R); + mul10(&MM); + if (use_mp) mul10(&MP); + } + + /* + printf("\nk = %d\n", k); + printf("R = "); print_big(&R); + printf("\nS = "); print_big(&S); + printf("\nM- = "); print_big(&MM); + if (use_mp) printf("\nM+ = "), print_big(&MP); + putchar('\n'); + fflush(0); + */ + + if (qr_shift) { + sl = s_n / 64; + slr = s_n % 64; + } + else { + big_shift_left(&S, 1, &S2); + add_big(&S2, &S, &S3); + big_shift_left(&S2, 1, &S4); + add_big(&S4, &S, &S5); + add_big(&S4, &S2, &S6); + add_big(&S4, &S3, &S7); + big_shift_left(&S4, 1, &S8); + add_big(&S8, &S, &S9); + } + +again: + if (qr_shift) { /* Take advantage of the fact that S = (ash 1 s_n) */ + if (R.l < sl) + d = 0; + else if (R.l == sl) { + Bigit *p; + + p = &R.d[sl]; + d = *p >> slr; + *p &= ((Bigit)1 << slr) - 1; + for (i = sl; (i > 0) && (*p == 0); i--) p--; + R.l = i; + } + else { + Bigit *p; + + p = &R.d[sl+1]; + d = *p << (64 - slr) | *(p-1) >> slr; + p--; + *p &= ((Bigit)1 << slr) - 1; + for (i = sl; (i > 0) && (*p == 0); i--) p--; + R.l = i; + } + } + else /* We need to do quotient-remainder */ + d = qr(); + + tc1 = big_comp(&R, &MM) < ruf; + tc2 = add_cmp() > -ruf; + if (!tc1) + if (!tc2) { + mul10(&R); + mul10(&MM); + if (use_mp) mul10(&MP); + *buf++ = d + '0'; + goto again; + } + else + OUTDIG(d+1) + else + if (!tc2) + OUTDIG(d) + else { + big_shift_left(&R, 1, &MM); + if (big_comp(&MM, &S) == -1) + OUTDIG(d) + else + OUTDIG(d+1) + } +} + +void +_PyFloat_DigitsInit() +{ + int n, i, l; + Bignum *b; + Bigit *xp, *zp, k; + + five[0].l = l = 0; + five[0].d[0] = 5; + for (n = MAX_FIVE-1, b = &five[0]; n > 0; n--) { + xp = &b->d[0]; + b++; + zp = &b->d[0]; + for (i = l, k = 0; i >= 0; i--) + MUL(*xp++, 5, *zp++, k); + if (k != 0) + *zp = k, l++; + b->l = l; + } + + /* + for (n = 1, b = &five[0]; n <= MAX_FIVE; n++) { + big_shift_left(b++, n, &R); + print_big(&R); + putchar('\n'); + } + fflush(0); + */ +} diff --git a/Objects/floatobject.c b/Objects/floatobject.c index c76956a..e92dab9 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -306,6 +306,107 @@ PyFloat_AsStringEx(char *buf, PyFloatObject *v, int precision) format_float(buf, 100, v, precision); } +/* The following function is based on Tcl_PrintDouble, + * from tclUtil.c. + */ + +#define is_infinite(d) ( (d) > DBL_MAX || (d) < -DBL_MAX ) +#define is_nan(d) ((d) != (d)) + +static void +format_double_repr(char *dst, double value) +{ + char *p, c; + int exp; + int signum; + char buffer[30]; + + /* + * Handle NaN. + */ + + if (is_nan(value)) { + strcpy(dst, "nan"); + return; + } + + /* + * Handle infinities. + */ + + if (is_infinite(value)) { + if (value < 0) { + strcpy(dst, "-inf"); + } else { + strcpy(dst, "inf"); + } + return; + } + + /* + * Ordinary (normal and denormal) values. + */ + + exp = _PyFloat_Digits(buffer, value, &signum)+1; + if (signum) { + *dst++ = '-'; + } + p = buffer; + if (exp < -3 || exp > 17) { + /* + * E format for numbers < 1e-3 or >= 1e17. + */ + + *dst++ = *p++; + c = *p; + if (c != '\0') { + *dst++ = '.'; + while (c != '\0') { + *dst++ = c; + c = *++p; + } + } + sprintf(dst, "e%+d", exp-1); + } else { + /* + * F format for others. + */ + + if (exp <= 0) { + *dst++ = '0'; + } + c = *p; + while (exp-- > 0) { + if (c != '\0') { + *dst++ = c; + c = *++p; + } else { + *dst++ = '0'; + } + } + *dst++ = '.'; + if (c == '\0') { + *dst++ = '0'; + } else { + while (++exp < 0) { + *dst++ = '0'; + } + while (c != '\0') { + *dst++ = c; + c = *++p; + } + } + *dst++ = '\0'; + } +} + +static void +format_float_repr(char *buf, PyFloatObject *v) +{ + assert(PyFloat_Check(v)); + format_double_repr(buf, PyFloat_AS_DOUBLE(v)); +} + /* Macro and helper that convert PyObject obj to a C double and store the value in dbl; this replaces the functionality of the coercion slot function. If conversion to double raises an exception, obj is @@ -390,8 +491,8 @@ float_print(PyFloatObject *v, FILE *fp, int flags) static PyObject * float_repr(PyFloatObject *v) { - char buf[100]; - format_float(buf, sizeof(buf), v, PREC_REPR); + char buf[30]; + format_float_repr(buf, v); return PyString_FromString(buf); } @@ -1290,6 +1391,9 @@ _PyFloat_Init(void) double_format = detected_double_format; float_format = detected_float_format; + + /* Initialize floating point repr */ + _PyFloat_DigitsInit(); } void diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj index 556b144..930deca 100644 --- a/PCbuild/pythoncore.vcproj +++ b/PCbuild/pythoncore.vcproj @@ -485,6 +485,9 @@ RelativePath="..\Objects\dictobject.c"> </File> <File + RelativePath="..\Objects\doubledigits.c"> + </File> + <File RelativePath="..\PC\dl_nt.c"> </File> <File diff --git a/PCbuild8/pythoncore/pythoncore.vcproj b/PCbuild8/pythoncore/pythoncore.vcproj index 6dd6867..f903c49 100644 --- a/PCbuild8/pythoncore/pythoncore.vcproj +++ b/PCbuild8/pythoncore/pythoncore.vcproj @@ -820,6 +820,10 @@ >
</File>
<File
+ RelativePath="..\..\Objects\doubledigits.c"
+ >
+ </File>
+ <File
RelativePath="..\..\Objects\enumobject.c"
>
</File>
diff --git a/PCbuild9/pythoncore.vcproj b/PCbuild9/pythoncore.vcproj index df1f512..ba41095 100644 --- a/PCbuild9/pythoncore.vcproj +++ b/PCbuild9/pythoncore.vcproj @@ -1371,6 +1371,10 @@ > </File> <File + RelativePath="..\Objects\doubledigits.c" + > + </File> + <File RelativePath="..\Objects\enumobject.c" > </File> |