paranoia.cc 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713
  1. /* A C version of Kahan's Floating Point Test "Paranoia"
  2. Thos Sumner, UCSF, Feb. 1985
  3. David Gay, BTL, Jan. 1986
  4. This is a rewrite from the Pascal version by
  5. B. A. Wichmann, 18 Jan. 1985
  6. (and does NOT exhibit good C programming style).
  7. Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
  8. (C) Apr 19 1983 in BASIC version by:
  9. Professor W. M. Kahan,
  10. 567 Evans Hall
  11. Electrical Engineering & Computer Science Dept.
  12. University of California
  13. Berkeley, California 94720
  14. USA
  15. converted to Pascal by:
  16. B. A. Wichmann
  17. National Physical Laboratory
  18. Teddington Middx
  19. TW11 OLW
  20. UK
  21. converted to C by:
  22. David M. Gay and Thos Sumner
  23. AT&T Bell Labs Computer Center, Rm. U-76
  24. 600 Mountain Avenue University of California
  25. Murray Hill, NJ 07974 San Francisco, CA 94143
  26. USA USA
  27. with simultaneous corrections to the Pascal source (reflected
  28. in the Pascal source available over netlib).
  29. [A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
  30. Reports of results on various systems from all the versions
  31. of Paranoia are being collected by Richard Karpinski at the
  32. same address as Thos Sumner. This includes sample outputs,
  33. bug reports, and criticisms.
  34. You may copy this program freely if you acknowledge its source.
  35. Comments on the Pascal version to NPL, please.
  36. The following is from the introductory commentary from Wichmann's work:
  37. The BASIC program of Kahan is written in Microsoft BASIC using many
  38. facilities which have no exact analogy in Pascal. The Pascal
  39. version below cannot therefore be exactly the same. Rather than be
  40. a minimal transcription of the BASIC program, the Pascal coding
  41. follows the conventional style of block-structured languages. Hence
  42. the Pascal version could be useful in producing versions in other
  43. structured languages.
  44. Rather than use identifiers of minimal length (which therefore have
  45. little mnemonic significance), the Pascal version uses meaningful
  46. identifiers as follows [Note: A few changes have been made for C]:
  47. BASIC C BASIC C BASIC C
  48. A J S StickyBit
  49. A1 AInverse J0 NoErrors T
  50. B Radix [Failure] T0 Underflow
  51. B1 BInverse J1 NoErrors T2 ThirtyTwo
  52. B2 RadixD2 [SeriousDefect] T5 OneAndHalf
  53. B9 BMinusU2 J2 NoErrors T7 TwentySeven
  54. C [Defect] T8 TwoForty
  55. C1 CInverse J3 NoErrors U OneUlp
  56. D [Flaw] U0 UnderflowThreshold
  57. D4 FourD K PageNo U1
  58. E0 L Milestone U2
  59. E1 M V
  60. E2 Exp2 N V0
  61. E3 N1 V8
  62. E5 MinSqEr O Zero V9
  63. E6 SqEr O1 One W
  64. E7 MaxSqEr O2 Two X
  65. E8 O3 Three X1
  66. E9 O4 Four X8
  67. F1 MinusOne O5 Five X9 Random1
  68. F2 Half O8 Eight Y
  69. F3 Third O9 Nine Y1
  70. F6 P Precision Y2
  71. F9 Q Y9 Random2
  72. G1 GMult Q8 Z
  73. G2 GDiv Q9 Z0 PseudoZero
  74. G3 GAddSub R Z1
  75. H R1 RMult Z2
  76. H1 HInverse R2 RDiv Z9
  77. I R3 RAddSub
  78. IO NoTrials R4 RSqrt
  79. I3 IEEE R9 Random9
  80. SqRWrng
  81. All the variables in BASIC are true variables and in consequence,
  82. the program is more difficult to follow since the "constants" must
  83. be determined (the glossary is very helpful). The Pascal version
  84. uses Real constants, but checks are added to ensure that the values
  85. are correctly converted by the compiler.
  86. The major textual change to the Pascal version apart from the
  87. identifiersis that named procedures are used, inserting parameters
  88. wherehelpful. New procedures are also introduced. The
  89. correspondence is as follows:
  90. BASIC Pascal
  91. lines
  92. 90- 140 Pause
  93. 170- 250 Instructions
  94. 380- 460 Heading
  95. 480- 670 Characteristics
  96. 690- 870 History
  97. 2940-2950 Random
  98. 3710-3740 NewD
  99. 4040-4080 DoesYequalX
  100. 4090-4110 PrintIfNPositive
  101. 4640-4850 TestPartialUnderflow
  102. */
  103. /* This version of paranoia has been modified to work with GCC's internal
  104. software floating point emulation library, as a sanity check of same.
  105. I'm doing this in C++ so that I can do operator overloading and not
  106. have to modify so damned much of the existing code. */
  107. extern "C" {
  108. #include <stdio.h>
  109. #include <stddef.h>
  110. #include <limits.h>
  111. #include <string.h>
  112. #include <stdlib.h>
  113. #include <math.h>
  114. #include <unistd.h>
  115. #include <float.h>
  116. /* This part is made all the more awful because many gcc headers are
  117. not prepared at all to be parsed as C++. The biggest stickler
  118. here is const structure members. So we include exactly the pieces
  119. that we need. */
  120. #define GTY(x)
  121. #include "ansidecl.h"
  122. #include "auto-host.h"
  123. #include "hwint.h"
  124. #undef EXTRA_MODES_FILE
  125. struct rtx_def;
  126. typedef struct rtx_def *rtx;
  127. struct rtvec_def;
  128. typedef struct rtvec_def *rtvec;
  129. union tree_node;
  130. typedef union tree_node *tree;
  131. #define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM,
  132. enum tree_code {
  133. #include "tree.def"
  134. LAST_AND_UNUSED_TREE_CODE
  135. };
  136. #undef DEFTREECODE
  137. #define class klass
  138. #include "real.h"
  139. #undef class
  140. }
  141. /* We never produce signals from the library. Thus setjmp need do nothing. */
  142. #undef setjmp
  143. #define setjmp(x) (0)
  144. static bool verbose = false;
  145. static int verbose_index = 0;
  146. /* ====================================================================== */
  147. /* The implementation of the abstract floating point class based on gcc's
  148. real.cc. I.e. the object of this exercise. Templated so that we can
  149. all fp sizes. */
  150. class real_c_float
  151. {
  152. public:
  153. static const enum machine_mode MODE = SFmode;
  154. private:
  155. static const int external_max = 128 / 32;
  156. static const int internal_max
  157. = (sizeof (REAL_VALUE_TYPE) + sizeof (long) + 1) / sizeof (long);
  158. long image[external_max < internal_max ? internal_max : external_max];
  159. void from_long(long);
  160. void from_str(const char *);
  161. void binop(int code, const real_c_float&);
  162. void unop(int code);
  163. bool cmp(int code, const real_c_float&) const;
  164. public:
  165. real_c_float()
  166. { }
  167. real_c_float(long l)
  168. { from_long(l); }
  169. real_c_float(const char *s)
  170. { from_str(s); }
  171. real_c_float(const real_c_float &b)
  172. { memcpy(image, b.image, sizeof(image)); }
  173. const real_c_float& operator= (long l)
  174. { from_long(l); return *this; }
  175. const real_c_float& operator= (const char *s)
  176. { from_str(s); return *this; }
  177. const real_c_float& operator= (const real_c_float &b)
  178. { memcpy(image, b.image, sizeof(image)); return *this; }
  179. const real_c_float& operator+= (const real_c_float &b)
  180. { binop(PLUS_EXPR, b); return *this; }
  181. const real_c_float& operator-= (const real_c_float &b)
  182. { binop(MINUS_EXPR, b); return *this; }
  183. const real_c_float& operator*= (const real_c_float &b)
  184. { binop(MULT_EXPR, b); return *this; }
  185. const real_c_float& operator/= (const real_c_float &b)
  186. { binop(RDIV_EXPR, b); return *this; }
  187. real_c_float operator- () const
  188. { real_c_float r(*this); r.unop(NEGATE_EXPR); return r; }
  189. real_c_float abs () const
  190. { real_c_float r(*this); r.unop(ABS_EXPR); return r; }
  191. bool operator < (const real_c_float &b) const { return cmp(LT_EXPR, b); }
  192. bool operator <= (const real_c_float &b) const { return cmp(LE_EXPR, b); }
  193. bool operator == (const real_c_float &b) const { return cmp(EQ_EXPR, b); }
  194. bool operator != (const real_c_float &b) const { return cmp(NE_EXPR, b); }
  195. bool operator >= (const real_c_float &b) const { return cmp(GE_EXPR, b); }
  196. bool operator > (const real_c_float &b) const { return cmp(GT_EXPR, b); }
  197. const char * str () const;
  198. const char * hex () const;
  199. long integer () const;
  200. int exp () const;
  201. void ldexp (int);
  202. };
  203. void
  204. real_c_float::from_long (long l)
  205. {
  206. REAL_VALUE_TYPE f;
  207. real_from_integer (&f, MODE, l, l < 0 ? -1 : 0, 0);
  208. real_to_target (image, &f, MODE);
  209. }
  210. void
  211. real_c_float::from_str (const char *s)
  212. {
  213. REAL_VALUE_TYPE f;
  214. const char *p = s;
  215. if (*p == '-' || *p == '+')
  216. p++;
  217. if (strcasecmp(p, "inf") == 0)
  218. {
  219. real_inf (&f);
  220. if (*s == '-')
  221. real_arithmetic (&f, NEGATE_EXPR, &f, NULL);
  222. }
  223. else if (strcasecmp(p, "nan") == 0)
  224. real_nan (&f, "", 1, MODE);
  225. else
  226. real_from_string (&f, s);
  227. real_to_target (image, &f, MODE);
  228. }
  229. void
  230. real_c_float::binop (int code, const real_c_float &b)
  231. {
  232. REAL_VALUE_TYPE ai, bi, ri;
  233. real_from_target (&ai, image, MODE);
  234. real_from_target (&bi, b.image, MODE);
  235. real_arithmetic (&ri, code, &ai, &bi);
  236. real_to_target (image, &ri, MODE);
  237. if (verbose)
  238. {
  239. char ab[64], bb[64], rb[64];
  240. const real_format *fmt = real_format_for_mode[MODE - QFmode];
  241. const int digits = (fmt->p * fmt->log2_b + 3) / 4;
  242. char symbol_for_code;
  243. real_from_target (&ri, image, MODE);
  244. real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
  245. real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
  246. real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
  247. switch (code)
  248. {
  249. case PLUS_EXPR:
  250. symbol_for_code = '+';
  251. break;
  252. case MINUS_EXPR:
  253. symbol_for_code = '-';
  254. break;
  255. case MULT_EXPR:
  256. symbol_for_code = '*';
  257. break;
  258. case RDIV_EXPR:
  259. symbol_for_code = '/';
  260. break;
  261. default:
  262. abort ();
  263. }
  264. fprintf (stderr, "%6d: %s %c %s = %s\n", verbose_index++,
  265. ab, symbol_for_code, bb, rb);
  266. }
  267. }
  268. void
  269. real_c_float::unop (int code)
  270. {
  271. REAL_VALUE_TYPE ai, ri;
  272. real_from_target (&ai, image, MODE);
  273. real_arithmetic (&ri, code, &ai, NULL);
  274. real_to_target (image, &ri, MODE);
  275. if (verbose)
  276. {
  277. char ab[64], rb[64];
  278. const real_format *fmt = real_format_for_mode[MODE - QFmode];
  279. const int digits = (fmt->p * fmt->log2_b + 3) / 4;
  280. const char *symbol_for_code;
  281. real_from_target (&ri, image, MODE);
  282. real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
  283. real_to_hexadecimal (rb, &ri, sizeof(rb), digits, 0);
  284. switch (code)
  285. {
  286. case NEGATE_EXPR:
  287. symbol_for_code = "-";
  288. break;
  289. case ABS_EXPR:
  290. symbol_for_code = "abs ";
  291. break;
  292. default:
  293. abort ();
  294. }
  295. fprintf (stderr, "%6d: %s%s = %s\n", verbose_index++,
  296. symbol_for_code, ab, rb);
  297. }
  298. }
  299. bool
  300. real_c_float::cmp (int code, const real_c_float &b) const
  301. {
  302. REAL_VALUE_TYPE ai, bi;
  303. bool ret;
  304. real_from_target (&ai, image, MODE);
  305. real_from_target (&bi, b.image, MODE);
  306. ret = real_compare (code, &ai, &bi);
  307. if (verbose)
  308. {
  309. char ab[64], bb[64];
  310. const real_format *fmt = real_format_for_mode[MODE - QFmode];
  311. const int digits = (fmt->p * fmt->log2_b + 3) / 4;
  312. const char *symbol_for_code;
  313. real_to_hexadecimal (ab, &ai, sizeof(ab), digits, 0);
  314. real_to_hexadecimal (bb, &bi, sizeof(bb), digits, 0);
  315. switch (code)
  316. {
  317. case LT_EXPR:
  318. symbol_for_code = "<";
  319. break;
  320. case LE_EXPR:
  321. symbol_for_code = "<=";
  322. break;
  323. case EQ_EXPR:
  324. symbol_for_code = "==";
  325. break;
  326. case NE_EXPR:
  327. symbol_for_code = "!=";
  328. break;
  329. case GE_EXPR:
  330. symbol_for_code = ">=";
  331. break;
  332. case GT_EXPR:
  333. symbol_for_code = ">";
  334. break;
  335. default:
  336. abort ();
  337. }
  338. fprintf (stderr, "%6d: %s %s %s = %s\n", verbose_index++,
  339. ab, symbol_for_code, bb, (ret ? "true" : "false"));
  340. }
  341. return ret;
  342. }
  343. const char *
  344. real_c_float::str() const
  345. {
  346. REAL_VALUE_TYPE f;
  347. const real_format *fmt = real_format_for_mode[MODE - QFmode];
  348. const int digits = int(fmt->p * fmt->log2_b * .30102999566398119521 + 1);
  349. real_from_target (&f, image, MODE);
  350. char *buf = new char[digits + 10];
  351. real_to_decimal (buf, &f, digits+10, digits, 0);
  352. return buf;
  353. }
  354. const char *
  355. real_c_float::hex() const
  356. {
  357. REAL_VALUE_TYPE f;
  358. const real_format *fmt = real_format_for_mode[MODE - QFmode];
  359. const int digits = (fmt->p * fmt->log2_b + 3) / 4;
  360. real_from_target (&f, image, MODE);
  361. char *buf = new char[digits + 10];
  362. real_to_hexadecimal (buf, &f, digits+10, digits, 0);
  363. return buf;
  364. }
  365. long
  366. real_c_float::integer() const
  367. {
  368. REAL_VALUE_TYPE f;
  369. real_from_target (&f, image, MODE);
  370. return real_to_integer (&f);
  371. }
  372. int
  373. real_c_float::exp() const
  374. {
  375. REAL_VALUE_TYPE f;
  376. real_from_target (&f, image, MODE);
  377. return real_exponent (&f);
  378. }
  379. void
  380. real_c_float::ldexp (int exp)
  381. {
  382. REAL_VALUE_TYPE ai;
  383. real_from_target (&ai, image, MODE);
  384. real_ldexp (&ai, &ai, exp);
  385. real_to_target (image, &ai, MODE);
  386. }
  387. /* ====================================================================== */
  388. /* An implementation of the abstract floating point class that uses native
  389. arithmetic. Exists for reference and debugging. */
  390. template<typename T>
  391. class native_float
  392. {
  393. private:
  394. // Force intermediate results back to memory.
  395. volatile T image;
  396. static T from_str (const char *);
  397. static T do_abs (T);
  398. static T verbose_binop (T, char, T, T);
  399. static T verbose_unop (const char *, T, T);
  400. static bool verbose_cmp (T, const char *, T, bool);
  401. public:
  402. native_float()
  403. { }
  404. native_float(long l)
  405. { image = l; }
  406. native_float(const char *s)
  407. { image = from_str(s); }
  408. native_float(const native_float &b)
  409. { image = b.image; }
  410. const native_float& operator= (long l)
  411. { image = l; return *this; }
  412. const native_float& operator= (const char *s)
  413. { image = from_str(s); return *this; }
  414. const native_float& operator= (const native_float &b)
  415. { image = b.image; return *this; }
  416. const native_float& operator+= (const native_float &b)
  417. {
  418. image = verbose_binop(image, '+', b.image, image + b.image);
  419. return *this;
  420. }
  421. const native_float& operator-= (const native_float &b)
  422. {
  423. image = verbose_binop(image, '-', b.image, image - b.image);
  424. return *this;
  425. }
  426. const native_float& operator*= (const native_float &b)
  427. {
  428. image = verbose_binop(image, '*', b.image, image * b.image);
  429. return *this;
  430. }
  431. const native_float& operator/= (const native_float &b)
  432. {
  433. image = verbose_binop(image, '/', b.image, image / b.image);
  434. return *this;
  435. }
  436. native_float operator- () const
  437. {
  438. native_float r;
  439. r.image = verbose_unop("-", image, -image);
  440. return r;
  441. }
  442. native_float abs () const
  443. {
  444. native_float r;
  445. r.image = verbose_unop("abs ", image, do_abs(image));
  446. return r;
  447. }
  448. bool operator < (const native_float &b) const
  449. { return verbose_cmp(image, "<", b.image, image < b.image); }
  450. bool operator <= (const native_float &b) const
  451. { return verbose_cmp(image, "<=", b.image, image <= b.image); }
  452. bool operator == (const native_float &b) const
  453. { return verbose_cmp(image, "==", b.image, image == b.image); }
  454. bool operator != (const native_float &b) const
  455. { return verbose_cmp(image, "!=", b.image, image != b.image); }
  456. bool operator >= (const native_float &b) const
  457. { return verbose_cmp(image, ">=", b.image, image >= b.image); }
  458. bool operator > (const native_float &b) const
  459. { return verbose_cmp(image, ">", b.image, image > b.image); }
  460. const char * str () const;
  461. const char * hex () const;
  462. long integer () const
  463. { return long(image); }
  464. int exp () const;
  465. void ldexp (int);
  466. };
  467. template<typename T>
  468. inline T
  469. native_float<T>::from_str (const char *s)
  470. {
  471. return strtold (s, NULL);
  472. }
  473. template<>
  474. inline float
  475. native_float<float>::from_str (const char *s)
  476. {
  477. return strtof (s, NULL);
  478. }
  479. template<>
  480. inline double
  481. native_float<double>::from_str (const char *s)
  482. {
  483. return strtod (s, NULL);
  484. }
  485. template<typename T>
  486. inline T
  487. native_float<T>::do_abs (T image)
  488. {
  489. return fabsl (image);
  490. }
  491. template<>
  492. inline float
  493. native_float<float>::do_abs (float image)
  494. {
  495. return fabsf (image);
  496. }
  497. template<>
  498. inline double
  499. native_float<double>::do_abs (double image)
  500. {
  501. return fabs (image);
  502. }
  503. template<typename T>
  504. T
  505. native_float<T>::verbose_binop (T a, char symbol, T b, T r)
  506. {
  507. if (verbose)
  508. {
  509. const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
  510. #ifdef NO_LONG_DOUBLE
  511. fprintf (stderr, "%6d: %.*a %c %.*a = %.*a\n", verbose_index++,
  512. digits, (double)a, symbol,
  513. digits, (double)b, digits, (double)r);
  514. #else
  515. fprintf (stderr, "%6d: %.*La %c %.*La = %.*La\n", verbose_index++,
  516. digits, (long double)a, symbol,
  517. digits, (long double)b, digits, (long double)r);
  518. #endif
  519. }
  520. return r;
  521. }
  522. template<typename T>
  523. T
  524. native_float<T>::verbose_unop (const char *symbol, T a, T r)
  525. {
  526. if (verbose)
  527. {
  528. const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
  529. #ifdef NO_LONG_DOUBLE
  530. fprintf (stderr, "%6d: %s%.*a = %.*a\n", verbose_index++,
  531. symbol, digits, (double)a, digits, (double)r);
  532. #else
  533. fprintf (stderr, "%6d: %s%.*La = %.*La\n", verbose_index++,
  534. symbol, digits, (long double)a, digits, (long double)r);
  535. #endif
  536. }
  537. return r;
  538. }
  539. template<typename T>
  540. bool
  541. native_float<T>::verbose_cmp (T a, const char *symbol, T b, bool r)
  542. {
  543. if (verbose)
  544. {
  545. const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
  546. #ifndef NO_LONG_DOUBLE
  547. fprintf (stderr, "%6d: %.*a %s %.*a = %s\n", verbose_index++,
  548. digits, (double)a, symbol,
  549. digits, (double)b, (r ? "true" : "false"));
  550. #else
  551. fprintf (stderr, "%6d: %.*La %s %.*La = %s\n", verbose_index++,
  552. digits, (long double)a, symbol,
  553. digits, (long double)b, (r ? "true" : "false"));
  554. #endif
  555. }
  556. return r;
  557. }
  558. template<typename T>
  559. const char *
  560. native_float<T>::str() const
  561. {
  562. char *buf = new char[50];
  563. const int digits = int(sizeof(T) * CHAR_BIT * .30102999566398119521 + 1);
  564. #ifndef NO_LONG_DOUBLE
  565. sprintf (buf, "%.*e", digits - 1, (double) image);
  566. #else
  567. sprintf (buf, "%.*Le", digits - 1, (long double) image);
  568. #endif
  569. return buf;
  570. }
  571. template<typename T>
  572. const char *
  573. native_float<T>::hex() const
  574. {
  575. char *buf = new char[50];
  576. const int digits = int(sizeof(T) * CHAR_BIT / 4);
  577. #ifndef NO_LONG_DOUBLE
  578. sprintf (buf, "%.*a", digits - 1, (double) image);
  579. #else
  580. sprintf (buf, "%.*La", digits - 1, (long double) image);
  581. #endif
  582. return buf;
  583. }
  584. template<typename T>
  585. int
  586. native_float<T>::exp() const
  587. {
  588. int e;
  589. frexp (image, &e);
  590. return e;
  591. }
  592. template<typename T>
  593. void
  594. native_float<T>::ldexp (int exp)
  595. {
  596. image = ldexpl (image, exp);
  597. }
  598. template<>
  599. void
  600. native_float<float>::ldexp (int exp)
  601. {
  602. image = ldexpf (image, exp);
  603. }
  604. template<>
  605. void
  606. native_float<double>::ldexp (int exp)
  607. {
  608. image = ::ldexp (image, exp);
  609. }
  610. /* ====================================================================== */
  611. /* Some libm routines that Paranoia expects to be available. */
  612. template<typename FLOAT>
  613. inline FLOAT
  614. FABS (const FLOAT &f)
  615. {
  616. return f.abs();
  617. }
  618. template<typename FLOAT, typename RHS>
  619. inline FLOAT
  620. operator+ (const FLOAT &a, const RHS &b)
  621. {
  622. return FLOAT(a) += FLOAT(b);
  623. }
  624. template<typename FLOAT, typename RHS>
  625. inline FLOAT
  626. operator- (const FLOAT &a, const RHS &b)
  627. {
  628. return FLOAT(a) -= FLOAT(b);
  629. }
  630. template<typename FLOAT, typename RHS>
  631. inline FLOAT
  632. operator* (const FLOAT &a, const RHS &b)
  633. {
  634. return FLOAT(a) *= FLOAT(b);
  635. }
  636. template<typename FLOAT, typename RHS>
  637. inline FLOAT
  638. operator/ (const FLOAT &a, const RHS &b)
  639. {
  640. return FLOAT(a) /= FLOAT(b);
  641. }
  642. template<typename FLOAT>
  643. FLOAT
  644. FLOOR (const FLOAT &f)
  645. {
  646. /* ??? This is only correct when F is representable as an integer. */
  647. long i = f.integer();
  648. FLOAT r;
  649. r = i;
  650. if (i < 0 && f != r)
  651. r = i - 1;
  652. return r;
  653. }
  654. template<typename FLOAT>
  655. FLOAT
  656. SQRT (const FLOAT &f)
  657. {
  658. #if 0
  659. FLOAT zero = long(0);
  660. FLOAT two = 2;
  661. FLOAT one = 1;
  662. FLOAT diff, diff2;
  663. FLOAT z, t;
  664. if (f == zero)
  665. return zero;
  666. if (f < zero)
  667. return zero / zero;
  668. if (f == one)
  669. return f;
  670. z = f;
  671. z.ldexp (-f.exp() / 2);
  672. diff2 = FABS (z * z - f);
  673. if (diff2 > zero)
  674. while (1)
  675. {
  676. t = (f / (two * z)) + (z / two);
  677. diff = FABS (t * t - f);
  678. if (diff >= diff2)
  679. break;
  680. z = t;
  681. diff2 = diff;
  682. }
  683. return z;
  684. #elif defined(NO_LONG_DOUBLE)
  685. double d;
  686. char buf[64];
  687. d = strtod (f.hex(), NULL);
  688. d = sqrt (d);
  689. sprintf(buf, "%.35a", d);
  690. return FLOAT(buf);
  691. #else
  692. long double ld;
  693. char buf[64];
  694. ld = strtold (f.hex(), NULL);
  695. ld = sqrtl (ld);
  696. sprintf(buf, "%.35La", ld);
  697. return FLOAT(buf);
  698. #endif
  699. }
  700. template<typename FLOAT>
  701. FLOAT
  702. LOG (FLOAT x)
  703. {
  704. #if 0
  705. FLOAT zero = long(0);
  706. FLOAT one = 1;
  707. if (x <= zero)
  708. return zero / zero;
  709. if (x == one)
  710. return zero;
  711. int exp = x.exp() - 1;
  712. x.ldexp(-exp);
  713. FLOAT xm1 = x - one;
  714. FLOAT y = xm1;
  715. long n = 2;
  716. FLOAT sum = xm1;
  717. while (1)
  718. {
  719. y *= xm1;
  720. FLOAT term = y / FLOAT (n);
  721. FLOAT next = sum + term;
  722. if (next == sum)
  723. break;
  724. sum = next;
  725. if (++n == 1000)
  726. break;
  727. }
  728. if (exp)
  729. sum += FLOAT (exp) * FLOAT(".69314718055994530941");
  730. return sum;
  731. #elif defined (NO_LONG_DOUBLE)
  732. double d;
  733. char buf[64];
  734. d = strtod (x.hex(), NULL);
  735. d = log (d);
  736. sprintf(buf, "%.35a", d);
  737. return FLOAT(buf);
  738. #else
  739. long double ld;
  740. char buf[64];
  741. ld = strtold (x.hex(), NULL);
  742. ld = logl (ld);
  743. sprintf(buf, "%.35La", ld);
  744. return FLOAT(buf);
  745. #endif
  746. }
  747. template<typename FLOAT>
  748. FLOAT
  749. EXP (const FLOAT &x)
  750. {
  751. /* Cheat. */
  752. #ifdef NO_LONG_DOUBLE
  753. double d;
  754. char buf[64];
  755. d = strtod (x.hex(), NULL);
  756. d = exp (d);
  757. sprintf(buf, "%.35a", d);
  758. return FLOAT(buf);
  759. #else
  760. long double ld;
  761. char buf[64];
  762. ld = strtold (x.hex(), NULL);
  763. ld = expl (ld);
  764. sprintf(buf, "%.35La", ld);
  765. return FLOAT(buf);
  766. #endif
  767. }
  768. template<typename FLOAT>
  769. FLOAT
  770. POW (const FLOAT &base, const FLOAT &exp)
  771. {
  772. /* Cheat. */
  773. #ifdef NO_LONG_DOUBLE
  774. double d1, d2;
  775. char buf[64];
  776. d1 = strtod (base.hex(), NULL);
  777. d2 = strtod (exp.hex(), NULL);
  778. d1 = pow (d1, d2);
  779. sprintf(buf, "%.35a", d1);
  780. return FLOAT(buf);
  781. #else
  782. long double ld1, ld2;
  783. char buf[64];
  784. ld1 = strtold (base.hex(), NULL);
  785. ld2 = strtold (exp.hex(), NULL);
  786. ld1 = powl (ld1, ld2);
  787. sprintf(buf, "%.35La", ld1);
  788. return FLOAT(buf);
  789. #endif
  790. }
  791. /* ====================================================================== */
  792. /* Real Paranoia begins again here. We wrap the thing in a template so
  793. that we can instantiate it for each floating point type we care for. */
  794. int NoTrials = 20; /*Number of tests for commutativity. */
  795. bool do_pause = false;
  796. enum Guard { No, Yes };
  797. enum Rounding { Other, Rounded, Chopped };
  798. enum Class { Failure, Serious, Defect, Flaw };
  799. template<typename FLOAT>
  800. struct Paranoia
  801. {
  802. FLOAT Radix, BInvrse, RadixD2, BMinusU2;
  803. /* Small floating point constants. */
  804. FLOAT Zero;
  805. FLOAT Half;
  806. FLOAT One;
  807. FLOAT Two;
  808. FLOAT Three;
  809. FLOAT Four;
  810. FLOAT Five;
  811. FLOAT Eight;
  812. FLOAT Nine;
  813. FLOAT TwentySeven;
  814. FLOAT ThirtyTwo;
  815. FLOAT TwoForty;
  816. FLOAT MinusOne;
  817. FLOAT OneAndHalf;
  818. /* Declarations of Variables. */
  819. int Indx;
  820. char ch[8];
  821. FLOAT AInvrse, A1;
  822. FLOAT C, CInvrse;
  823. FLOAT D, FourD;
  824. FLOAT E0, E1, Exp2, E3, MinSqEr;
  825. FLOAT SqEr, MaxSqEr, E9;
  826. FLOAT Third;
  827. FLOAT F6, F9;
  828. FLOAT H, HInvrse;
  829. int I;
  830. FLOAT StickyBit, J;
  831. FLOAT MyZero;
  832. FLOAT Precision;
  833. FLOAT Q, Q9;
  834. FLOAT R, Random9;
  835. FLOAT T, Underflow, S;
  836. FLOAT OneUlp, UfThold, U1, U2;
  837. FLOAT V, V0, V9;
  838. FLOAT W;
  839. FLOAT X, X1, X2, X8, Random1;
  840. FLOAT Y, Y1, Y2, Random2;
  841. FLOAT Z, PseudoZero, Z1, Z2, Z9;
  842. int ErrCnt[4];
  843. int Milestone;
  844. int PageNo;
  845. int M, N, N1;
  846. Guard GMult, GDiv, GAddSub;
  847. Rounding RMult, RDiv, RAddSub, RSqrt;
  848. int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad;
  849. /* Computed constants. */
  850. /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
  851. /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
  852. int main ();
  853. FLOAT Sign (FLOAT);
  854. FLOAT Random ();
  855. void Pause ();
  856. void BadCond (int, const char *);
  857. void SqXMinX (int);
  858. void TstCond (int, int, const char *);
  859. void notify (const char *);
  860. void IsYeqX ();
  861. void NewD ();
  862. void PrintIfNPositive ();
  863. void SR3750 ();
  864. void TstPtUf ();
  865. // Pretend we're bss.
  866. Paranoia() { memset(this, 0, sizeof (*this)); }
  867. };
  868. template<typename FLOAT>
  869. int
  870. Paranoia<FLOAT>::main()
  871. {
  872. /* First two assignments use integer right-hand sides. */
  873. Zero = long(0);
  874. One = long(1);
  875. Two = long(2);
  876. Three = long(3);
  877. Four = long(4);
  878. Five = long(5);
  879. Eight = long(8);
  880. Nine = long(9);
  881. TwentySeven = long(27);
  882. ThirtyTwo = long(32);
  883. TwoForty = long(240);
  884. MinusOne = long(-1);
  885. Half = "0x1p-1";
  886. OneAndHalf = "0x3p-1";
  887. ErrCnt[Failure] = 0;
  888. ErrCnt[Serious] = 0;
  889. ErrCnt[Defect] = 0;
  890. ErrCnt[Flaw] = 0;
  891. PageNo = 1;
  892. /*=============================================*/
  893. Milestone = 7;
  894. /*=============================================*/
  895. printf ("Program is now RUNNING tests on small integers:\n");
  896. TstCond (Failure, (Zero + Zero == Zero), "0+0 != 0");
  897. TstCond (Failure, (One - One == Zero), "1-1 != 0");
  898. TstCond (Failure, (One > Zero), "1 <= 0");
  899. TstCond (Failure, (One + One == Two), "1+1 != 2");
  900. Z = -Zero;
  901. if (Z != Zero)
  902. {
  903. ErrCnt[Failure] = ErrCnt[Failure] + 1;
  904. printf ("Comparison alleges that -0.0 is Non-zero!\n");
  905. U2 = "0.001";
  906. Radix = 1;
  907. TstPtUf ();
  908. }
  909. TstCond (Failure, (Three == Two + One), "3 != 2+1");
  910. TstCond (Failure, (Four == Three + One), "4 != 3+1");
  911. TstCond (Failure, (Four + Two * (-Two) == Zero), "4 + 2*(-2) != 0");
  912. TstCond (Failure, (Four - Three - One == Zero), "4-3-1 != 0");
  913. TstCond (Failure, (MinusOne == (Zero - One)), "-1 != 0-1");
  914. TstCond (Failure, (MinusOne + One == Zero), "-1+1 != 0");
  915. TstCond (Failure, (One + MinusOne == Zero), "1+(-1) != 0");
  916. TstCond (Failure, (MinusOne + FABS (One) == Zero), "-1+abs(1) != 0");
  917. TstCond (Failure, (MinusOne + MinusOne * MinusOne == Zero),
  918. "-1+(-1)*(-1) != 0");
  919. TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0");
  920. /*=============================================*/
  921. Milestone = 10;
  922. /*=============================================*/
  923. TstCond (Failure, (Nine == Three * Three), "9 != 3*3");
  924. TstCond (Failure, (TwentySeven == Nine * Three), "27 != 9*3");
  925. TstCond (Failure, (Eight == Four + Four), "8 != 4+4");
  926. TstCond (Failure, (ThirtyTwo == Eight * Four), "32 != 8*4");
  927. TstCond (Failure, (ThirtyTwo - TwentySeven - Four - One == Zero),
  928. "32-27-4-1 != 0");
  929. TstCond (Failure, Five == Four + One, "5 != 4+1");
  930. TstCond (Failure, TwoForty == Four * Five * Three * Four, "240 != 4*5*3*4");
  931. TstCond (Failure, TwoForty / Three - Four * Four * Five == Zero,
  932. "240/3 - 4*4*5 != 0");
  933. TstCond (Failure, TwoForty / Four - Five * Three * Four == Zero,
  934. "240/4 - 5*3*4 != 0");
  935. TstCond (Failure, TwoForty / Five - Four * Three * Four == Zero,
  936. "240/5 - 4*3*4 != 0");
  937. if (ErrCnt[Failure] == 0)
  938. {
  939. printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
  940. printf ("\n");
  941. }
  942. printf ("Searching for Radix and Precision.\n");
  943. W = One;
  944. do
  945. {
  946. W = W + W;
  947. Y = W + One;
  948. Z = Y - W;
  949. Y = Z - One;
  950. }
  951. while (MinusOne + FABS (Y) < Zero);
  952. /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
  953. Precision = Zero;
  954. Y = One;
  955. do
  956. {
  957. Radix = W + Y;
  958. Y = Y + Y;
  959. Radix = Radix - W;
  960. }
  961. while (Radix == Zero);
  962. if (Radix < Two)
  963. Radix = One;
  964. printf ("Radix = %s .\n", Radix.str());
  965. if (Radix != One)
  966. {
  967. W = One;
  968. do
  969. {
  970. Precision = Precision + One;
  971. W = W * Radix;
  972. Y = W + One;
  973. }
  974. while ((Y - W) == One);
  975. }
  976. /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
  977. ... */
  978. U1 = One / W;
  979. U2 = Radix * U1;
  980. printf ("Closest relative separation found is U1 = %s .\n\n", U1.str());
  981. printf ("Recalculating radix and precision\n ");
  982. /*save old values */
  983. E0 = Radix;
  984. E1 = U1;
  985. E9 = U2;
  986. E3 = Precision;
  987. X = Four / Three;
  988. Third = X - One;
  989. F6 = Half - Third;
  990. X = F6 + F6;
  991. X = FABS (X - Third);
  992. if (X < U2)
  993. X = U2;
  994. /*... now X = (unknown no.) ulps of 1+... */
  995. do
  996. {
  997. U2 = X;
  998. Y = Half * U2 + ThirtyTwo * U2 * U2;
  999. Y = One + Y;
  1000. X = Y - One;
  1001. }
  1002. while (!((U2 <= X) || (X <= Zero)));
  1003. /*... now U2 == 1 ulp of 1 + ... */
  1004. X = Two / Three;
  1005. F6 = X - Half;
  1006. Third = F6 + F6;
  1007. X = Third - Half;
  1008. X = FABS (X + F6);
  1009. if (X < U1)
  1010. X = U1;
  1011. /*... now X == (unknown no.) ulps of 1 -... */
  1012. do
  1013. {
  1014. U1 = X;
  1015. Y = Half * U1 + ThirtyTwo * U1 * U1;
  1016. Y = Half - Y;
  1017. X = Half + Y;
  1018. Y = Half - X;
  1019. X = Half + Y;
  1020. }
  1021. while (!((U1 <= X) || (X <= Zero)));
  1022. /*... now U1 == 1 ulp of 1 - ... */
  1023. if (U1 == E1)
  1024. printf ("confirms closest relative separation U1 .\n");
  1025. else
  1026. printf ("gets better closest relative separation U1 = %s .\n", U1.str());
  1027. W = One / U1;
  1028. F9 = (Half - U1) + Half;
  1029. Radix = FLOOR (FLOAT ("0.01") + U2 / U1);
  1030. if (Radix == E0)
  1031. printf ("Radix confirmed.\n");
  1032. else
  1033. printf ("MYSTERY: recalculated Radix = %s .\n", Radix.str());
  1034. TstCond (Defect, Radix <= Eight + Eight,
  1035. "Radix is too big: roundoff problems");
  1036. TstCond (Flaw, (Radix == Two) || (Radix == 10)
  1037. || (Radix == One), "Radix is not as good as 2 or 10");
  1038. /*=============================================*/
  1039. Milestone = 20;
  1040. /*=============================================*/
  1041. TstCond (Failure, F9 - Half < Half,
  1042. "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
  1043. X = F9;
  1044. I = 1;
  1045. Y = X - Half;
  1046. Z = Y - Half;
  1047. TstCond (Failure, (X != One)
  1048. || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
  1049. X = One + U2;
  1050. I = 0;
  1051. /*=============================================*/
  1052. Milestone = 25;
  1053. /*=============================================*/
  1054. /*... BMinusU2 = nextafter(Radix, 0) */
  1055. BMinusU2 = Radix - One;
  1056. BMinusU2 = (BMinusU2 - U2) + One;
  1057. /* Purify Integers */
  1058. if (Radix != One)
  1059. {
  1060. X = -TwoForty * LOG (U1) / LOG (Radix);
  1061. Y = FLOOR (Half + X);
  1062. if (FABS (X - Y) * Four < One)
  1063. X = Y;
  1064. Precision = X / TwoForty;
  1065. Y = FLOOR (Half + Precision);
  1066. if (FABS (Precision - Y) * TwoForty < Half)
  1067. Precision = Y;
  1068. }
  1069. if ((Precision != FLOOR (Precision)) || (Radix == One))
  1070. {
  1071. printf ("Precision cannot be characterized by an Integer number\n");
  1072. printf
  1073. ("of significant digits but, by itself, this is a minor flaw.\n");
  1074. }
  1075. if (Radix == One)
  1076. printf
  1077. ("logarithmic encoding has precision characterized solely by U1.\n");
  1078. else
  1079. printf ("The number of significant digits of the Radix is %s .\n",
  1080. Precision.str());
  1081. TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
  1082. "Precision worse than 5 decimal figures ");
  1083. /*=============================================*/
  1084. Milestone = 30;
  1085. /*=============================================*/
  1086. /* Test for extra-precise subexpressions */
  1087. X = FABS (((Four / Three - One) - One / Four) * Three - One / Four);
  1088. do
  1089. {
  1090. Z2 = X;
  1091. X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
  1092. }
  1093. while (!((Z2 <= X) || (X <= Zero)));
  1094. X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four);
  1095. do
  1096. {
  1097. Z1 = Z;
  1098. Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
  1099. + One / Two)) + One / Two;
  1100. }
  1101. while (!((Z1 <= Z) || (Z <= Zero)));
  1102. do
  1103. {
  1104. do
  1105. {
  1106. Y1 = Y;
  1107. Y =
  1108. (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half)) +
  1109. Half;
  1110. }
  1111. while (!((Y1 <= Y) || (Y <= Zero)));
  1112. X1 = X;
  1113. X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
  1114. }
  1115. while (!((X1 <= X) || (X <= Zero)));
  1116. if ((X1 != Y1) || (X1 != Z1))
  1117. {
  1118. BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n");
  1119. printf ("respectively %s, %s, %s,\n", X1.str(), Y1.str(), Z1.str());
  1120. printf ("are symptoms of inconsistencies introduced\n");
  1121. printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
  1122. notify ("Possibly some part of this");
  1123. if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))
  1124. printf ("That feature is not tested further by this program.\n");
  1125. }
  1126. else
  1127. {
  1128. if ((Z1 != U1) || (Z2 != U2))
  1129. {
  1130. if ((Z1 >= U1) || (Z2 >= U2))
  1131. {
  1132. BadCond (Failure, "");
  1133. notify ("Precision");
  1134. printf ("\tU1 = %s, Z1 - U1 = %s\n", U1.str(), (Z1 - U1).str());
  1135. printf ("\tU2 = %s, Z2 - U2 = %s\n", U2.str(), (Z2 - U2).str());
  1136. }
  1137. else
  1138. {
  1139. if ((Z1 <= Zero) || (Z2 <= Zero))
  1140. {
  1141. printf ("Because of unusual Radix = %s", Radix.str());
  1142. printf (", or exact rational arithmetic a result\n");
  1143. printf ("Z1 = %s, or Z2 = %s ", Z1.str(), Z2.str());
  1144. notify ("of an\nextra-precision");
  1145. }
  1146. if (Z1 != Z2 || Z1 > Zero)
  1147. {
  1148. X = Z1 / U1;
  1149. Y = Z2 / U2;
  1150. if (Y > X)
  1151. X = Y;
  1152. Q = -LOG (X);
  1153. printf ("Some subexpressions appear to be calculated "
  1154. "extra precisely\n");
  1155. printf ("with about %s extra B-digits, i.e.\n",
  1156. (Q / LOG (Radix)).str());
  1157. printf ("roughly %s extra significant decimals.\n",
  1158. (Q / LOG (FLOAT (10))).str());
  1159. }
  1160. printf
  1161. ("That feature is not tested further by this program.\n");
  1162. }
  1163. }
  1164. }
  1165. Pause ();
  1166. /*=============================================*/
  1167. Milestone = 35;
  1168. /*=============================================*/
  1169. if (Radix >= Two)
  1170. {
  1171. X = W / (Radix * Radix);
  1172. Y = X + One;
  1173. Z = Y - X;
  1174. T = Z + U2;
  1175. X = T - Z;
  1176. TstCond (Failure, X == U2,
  1177. "Subtraction is not normalized X=Y,X+Z != Y+Z!");
  1178. if (X == U2)
  1179. printf ("Subtraction appears to be normalized, as it should be.");
  1180. }
  1181. printf ("\nChecking for guard digit in *, /, and -.\n");
  1182. Y = F9 * One;
  1183. Z = One * F9;
  1184. X = F9 - Half;
  1185. Y = (Y - Half) - X;
  1186. Z = (Z - Half) - X;
  1187. X = One + U2;
  1188. T = X * Radix;
  1189. R = Radix * X;
  1190. X = T - Radix;
  1191. X = X - Radix * U2;
  1192. T = R - Radix;
  1193. T = T - Radix * U2;
  1194. X = X * (Radix - One);
  1195. T = T * (Radix - One);
  1196. if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero))
  1197. GMult = Yes;
  1198. else
  1199. {
  1200. GMult = No;
  1201. TstCond (Serious, false, "* lacks a Guard Digit, so 1*X != X");
  1202. }
  1203. Z = Radix * U2;
  1204. X = One + Z;
  1205. Y = FABS ((X + Z) - X * X) - U2;
  1206. X = One - U2;
  1207. Z = FABS ((X - U2) - X * X) - U1;
  1208. TstCond (Failure, (Y <= Zero)
  1209. && (Z <= Zero), "* gets too many final digits wrong.\n");
  1210. Y = One - U2;
  1211. X = One + U2;
  1212. Z = One / Y;
  1213. Y = Z - X;
  1214. X = One / Three;
  1215. Z = Three / Nine;
  1216. X = X - Z;
  1217. T = Nine / TwentySeven;
  1218. Z = Z - T;
  1219. TstCond (Defect, X == Zero && Y == Zero && Z == Zero,
  1220. "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
  1221. "or 1/3 and 3/9 and 9/27 may disagree");
  1222. Y = F9 / One;
  1223. X = F9 - Half;
  1224. Y = (Y - Half) - X;
  1225. X = One + U2;
  1226. T = X / One;
  1227. X = T - X;
  1228. if ((X == Zero) && (Y == Zero) && (Z == Zero))
  1229. GDiv = Yes;
  1230. else
  1231. {
  1232. GDiv = No;
  1233. TstCond (Serious, false, "Division lacks a Guard Digit, so X/1 != X");
  1234. }
  1235. X = One / (One + U2);
  1236. Y = X - Half - Half;
  1237. TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1");
  1238. X = One - U2;
  1239. Y = One + Radix * U2;
  1240. Z = X * Radix;
  1241. T = Y * Radix;
  1242. R = Z / Radix;
  1243. StickyBit = T / Radix;
  1244. X = R - X;
  1245. Y = StickyBit - Y;
  1246. TstCond (Failure, X == Zero && Y == Zero,
  1247. "* and/or / gets too many last digits wrong");
  1248. Y = One - U1;
  1249. X = One - F9;
  1250. Y = One - Y;
  1251. T = Radix - U2;
  1252. Z = Radix - BMinusU2;
  1253. T = Radix - T;
  1254. if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2))
  1255. GAddSub = Yes;
  1256. else
  1257. {
  1258. GAddSub = No;
  1259. TstCond (Serious, false,
  1260. "- lacks Guard Digit, so cancellation is obscured");
  1261. }
  1262. if (F9 != One && F9 - One >= Zero)
  1263. {
  1264. BadCond (Serious, "comparison alleges (1-U1) < 1 although\n");
  1265. printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n");
  1266. printf (" such precautions against division by zero as\n");
  1267. printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
  1268. }
  1269. if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
  1270. printf
  1271. (" *, /, and - appear to have guard digits, as they should.\n");
  1272. /*=============================================*/
  1273. Milestone = 40;
  1274. /*=============================================*/
  1275. Pause ();
  1276. printf ("Checking rounding on multiply, divide and add/subtract.\n");
  1277. RMult = Other;
  1278. RDiv = Other;
  1279. RAddSub = Other;
  1280. RadixD2 = Radix / Two;
  1281. A1 = Two;
  1282. Done = false;
  1283. do
  1284. {
  1285. AInvrse = Radix;
  1286. do
  1287. {
  1288. X = AInvrse;
  1289. AInvrse = AInvrse / A1;
  1290. }
  1291. while (!(FLOOR (AInvrse) != AInvrse));
  1292. Done = (X == One) || (A1 > Three);
  1293. if (!Done)
  1294. A1 = Nine + One;
  1295. }
  1296. while (!(Done));
  1297. if (X == One)
  1298. A1 = Radix;
  1299. AInvrse = One / A1;
  1300. X = A1;
  1301. Y = AInvrse;
  1302. Done = false;
  1303. do
  1304. {
  1305. Z = X * Y - Half;
  1306. TstCond (Failure, Z == Half, "X * (1/X) differs from 1");
  1307. Done = X == Radix;
  1308. X = Radix;
  1309. Y = One / X;
  1310. }
  1311. while (!(Done));
  1312. Y2 = One + U2;
  1313. Y1 = One - U2;
  1314. X = OneAndHalf - U2;
  1315. Y = OneAndHalf + U2;
  1316. Z = (X - U2) * Y2;
  1317. T = Y * Y1;
  1318. Z = Z - X;
  1319. T = T - X;
  1320. X = X * Y2;
  1321. Y = (Y + U2) * Y1;
  1322. X = X - OneAndHalf;
  1323. Y = Y - OneAndHalf;
  1324. if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero))
  1325. {
  1326. X = (OneAndHalf + U2) * Y2;
  1327. Y = OneAndHalf - U2 - U2;
  1328. Z = OneAndHalf + U2 + U2;
  1329. T = (OneAndHalf - U2) * Y1;
  1330. X = X - (Z + U2);
  1331. StickyBit = Y * Y1;
  1332. S = Z * Y2;
  1333. T = T - Y;
  1334. Y = (U2 - Y) + StickyBit;
  1335. Z = S - (Z + U2 + U2);
  1336. StickyBit = (Y2 + U2) * Y1;
  1337. Y1 = Y2 * Y1;
  1338. StickyBit = StickyBit - Y2;
  1339. Y1 = Y1 - Half;
  1340. if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
  1341. && (StickyBit == Zero) && (Y1 == Half))
  1342. {
  1343. RMult = Rounded;
  1344. printf ("Multiplication appears to round correctly.\n");
  1345. }
  1346. else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
  1347. && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half))
  1348. {
  1349. RMult = Chopped;
  1350. printf ("Multiplication appears to chop.\n");
  1351. }
  1352. else
  1353. printf ("* is neither chopped nor correctly rounded.\n");
  1354. if ((RMult == Rounded) && (GMult == No))
  1355. notify ("Multiplication");
  1356. }
  1357. else
  1358. printf ("* is neither chopped nor correctly rounded.\n");
  1359. /*=============================================*/
  1360. Milestone = 45;
  1361. /*=============================================*/
  1362. Y2 = One + U2;
  1363. Y1 = One - U2;
  1364. Z = OneAndHalf + U2 + U2;
  1365. X = Z / Y2;
  1366. T = OneAndHalf - U2 - U2;
  1367. Y = (T - U2) / Y1;
  1368. Z = (Z + U2) / Y2;
  1369. X = X - OneAndHalf;
  1370. Y = Y - T;
  1371. T = T / Y1;
  1372. Z = Z - (OneAndHalf + U2);
  1373. T = (U2 - OneAndHalf) + T;
  1374. if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero)))
  1375. {
  1376. X = OneAndHalf / Y2;
  1377. Y = OneAndHalf - U2;
  1378. Z = OneAndHalf + U2;
  1379. X = X - Y;
  1380. T = OneAndHalf / Y1;
  1381. Y = Y / Y1;
  1382. T = T - (Z + U2);
  1383. Y = Y - Z;
  1384. Z = Z / Y2;
  1385. Y1 = (Y2 + U2) / Y2;
  1386. Z = Z - OneAndHalf;
  1387. Y2 = Y1 - Y2;
  1388. Y1 = (F9 - U1) / F9;
  1389. if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
  1390. && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half))
  1391. {
  1392. RDiv = Rounded;
  1393. printf ("Division appears to round correctly.\n");
  1394. if (GDiv == No)
  1395. notify ("Division");
  1396. }
  1397. else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
  1398. && (Y2 < Zero) && (Y1 - Half < F9 - Half))
  1399. {
  1400. RDiv = Chopped;
  1401. printf ("Division appears to chop.\n");
  1402. }
  1403. }
  1404. if (RDiv == Other)
  1405. printf ("/ is neither chopped nor correctly rounded.\n");
  1406. BInvrse = One / Radix;
  1407. TstCond (Failure, (BInvrse * Radix - Half == Half),
  1408. "Radix * ( 1 / Radix ) differs from 1");
  1409. /*=============================================*/
  1410. Milestone = 50;
  1411. /*=============================================*/
  1412. TstCond (Failure, ((F9 + U1) - Half == Half)
  1413. && ((BMinusU2 + U2) - One == Radix - One),
  1414. "Incomplete carry-propagation in Addition");
  1415. X = One - U1 * U1;
  1416. Y = One + U2 * (One - U2);
  1417. Z = F9 - Half;
  1418. X = (X - Half) - Z;
  1419. Y = Y - One;
  1420. if ((X == Zero) && (Y == Zero))
  1421. {
  1422. RAddSub = Chopped;
  1423. printf ("Add/Subtract appears to be chopped.\n");
  1424. }
  1425. if (GAddSub == Yes)
  1426. {
  1427. X = (Half + U2) * U2;
  1428. Y = (Half - U2) * U2;
  1429. X = One + X;
  1430. Y = One + Y;
  1431. X = (One + U2) - X;
  1432. Y = One - Y;
  1433. if ((X == Zero) && (Y == Zero))
  1434. {
  1435. X = (Half + U2) * U1;
  1436. Y = (Half - U2) * U1;
  1437. X = One - X;
  1438. Y = One - Y;
  1439. X = F9 - X;
  1440. Y = One - Y;
  1441. if ((X == Zero) && (Y == Zero))
  1442. {
  1443. RAddSub = Rounded;
  1444. printf ("Addition/Subtraction appears to round correctly.\n");
  1445. if (GAddSub == No)
  1446. notify ("Add/Subtract");
  1447. }
  1448. else
  1449. printf ("Addition/Subtraction neither rounds nor chops.\n");
  1450. }
  1451. else
  1452. printf ("Addition/Subtraction neither rounds nor chops.\n");
  1453. }
  1454. else
  1455. printf ("Addition/Subtraction neither rounds nor chops.\n");
  1456. S = One;
  1457. X = One + Half * (One + Half);
  1458. Y = (One + U2) * Half;
  1459. Z = X - Y;
  1460. T = Y - X;
  1461. StickyBit = Z + T;
  1462. if (StickyBit != Zero)
  1463. {
  1464. S = Zero;
  1465. BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n");
  1466. }
  1467. StickyBit = Zero;
  1468. if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
  1469. && (RMult == Rounded) && (RDiv == Rounded)
  1470. && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2))
  1471. {
  1472. printf ("Checking for sticky bit.\n");
  1473. X = (Half + U1) * U2;
  1474. Y = Half * U2;
  1475. Z = One + Y;
  1476. T = One + X;
  1477. if ((Z - One <= Zero) && (T - One >= U2))
  1478. {
  1479. Z = T + Y;
  1480. Y = Z - X;
  1481. if ((Z - T >= U2) && (Y - T == Zero))
  1482. {
  1483. X = (Half + U1) * U1;
  1484. Y = Half * U1;
  1485. Z = One - Y;
  1486. T = One - X;
  1487. if ((Z - One == Zero) && (T - F9 == Zero))
  1488. {
  1489. Z = (Half - U1) * U1;
  1490. T = F9 - Z;
  1491. Q = F9 - Y;
  1492. if ((T - F9 == Zero) && (F9 - U1 - Q == Zero))
  1493. {
  1494. Z = (One + U2) * OneAndHalf;
  1495. T = (OneAndHalf + U2) - Z + U2;
  1496. X = One + Half / Radix;
  1497. Y = One + Radix * U2;
  1498. Z = X * Y;
  1499. if (T == Zero && X + Radix * U2 - Z == Zero)
  1500. {
  1501. if (Radix != Two)
  1502. {
  1503. X = Two + U2;
  1504. Y = X / Two;
  1505. if ((Y - One == Zero))
  1506. StickyBit = S;
  1507. }
  1508. else
  1509. StickyBit = S;
  1510. }
  1511. }
  1512. }
  1513. }
  1514. }
  1515. }
  1516. if (StickyBit == One)
  1517. printf ("Sticky bit apparently used correctly.\n");
  1518. else
  1519. printf ("Sticky bit used incorrectly or not at all.\n");
  1520. TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
  1521. RMult == Other || RDiv == Other || RAddSub == Other),
  1522. "lack(s) of guard digits or failure(s) to correctly round or chop\n\
  1523. (noted above) count as one flaw in the final tally below");
  1524. /*=============================================*/
  1525. Milestone = 60;
  1526. /*=============================================*/
  1527. printf ("\n");
  1528. printf ("Does Multiplication commute? ");
  1529. printf ("Testing on %d random pairs.\n", NoTrials);
  1530. Random9 = SQRT (FLOAT (3));
  1531. Random1 = Third;
  1532. I = 1;
  1533. do
  1534. {
  1535. X = Random ();
  1536. Y = Random ();
  1537. Z9 = Y * X;
  1538. Z = X * Y;
  1539. Z9 = Z - Z9;
  1540. I = I + 1;
  1541. }
  1542. while (!((I > NoTrials) || (Z9 != Zero)));
  1543. if (I == NoTrials)
  1544. {
  1545. Random1 = One + Half / Three;
  1546. Random2 = (U2 + U1) + One;
  1547. Z = Random1 * Random2;
  1548. Y = Random2 * Random1;
  1549. Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
  1550. Three) * ((U2 + U1) +
  1551. One);
  1552. }
  1553. if (!((I == NoTrials) || (Z9 == Zero)))
  1554. BadCond (Defect, "X * Y == Y * X trial fails.\n");
  1555. else
  1556. printf (" No failures found in %d integer pairs.\n", NoTrials);
  1557. /*=============================================*/
  1558. Milestone = 70;
  1559. /*=============================================*/
  1560. printf ("\nRunning test of square root(x).\n");
  1561. TstCond (Failure, (Zero == SQRT (Zero))
  1562. && (-Zero == SQRT (-Zero))
  1563. && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong");
  1564. MinSqEr = Zero;
  1565. MaxSqEr = Zero;
  1566. J = Zero;
  1567. X = Radix;
  1568. OneUlp = U2;
  1569. SqXMinX (Serious);
  1570. X = BInvrse;
  1571. OneUlp = BInvrse * U1;
  1572. SqXMinX (Serious);
  1573. X = U1;
  1574. OneUlp = U1 * U1;
  1575. SqXMinX (Serious);
  1576. if (J != Zero)
  1577. Pause ();
  1578. printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
  1579. J = Zero;
  1580. X = Two;
  1581. Y = Radix;
  1582. if ((Radix != One))
  1583. do
  1584. {
  1585. X = Y;
  1586. Y = Radix * Y;
  1587. }
  1588. while (!((Y - X >= NoTrials)));
  1589. OneUlp = X * U2;
  1590. I = 1;
  1591. while (I <= NoTrials)
  1592. {
  1593. X = X + One;
  1594. SqXMinX (Defect);
  1595. if (J > Zero)
  1596. break;
  1597. I = I + 1;
  1598. }
  1599. printf ("Test for sqrt monotonicity.\n");
  1600. I = -1;
  1601. X = BMinusU2;
  1602. Y = Radix;
  1603. Z = Radix + Radix * U2;
  1604. NotMonot = false;
  1605. Monot = false;
  1606. while (!(NotMonot || Monot))
  1607. {
  1608. I = I + 1;
  1609. X = SQRT (X);
  1610. Q = SQRT (Y);
  1611. Z = SQRT (Z);
  1612. if ((X > Q) || (Q > Z))
  1613. NotMonot = true;
  1614. else
  1615. {
  1616. Q = FLOOR (Q + Half);
  1617. if (!(I > 0 || Radix == Q * Q))
  1618. Monot = true;
  1619. else if (I > 0)
  1620. {
  1621. if (I > 1)
  1622. Monot = true;
  1623. else
  1624. {
  1625. Y = Y * BInvrse;
  1626. X = Y - U1;
  1627. Z = Y + U1;
  1628. }
  1629. }
  1630. else
  1631. {
  1632. Y = Q;
  1633. X = Y - U2;
  1634. Z = Y + U2;
  1635. }
  1636. }
  1637. }
  1638. if (Monot)
  1639. printf ("sqrt has passed a test for Monotonicity.\n");
  1640. else
  1641. {
  1642. BadCond (Defect, "");
  1643. printf ("sqrt(X) is non-monotonic for X near %s .\n", Y.str());
  1644. }
  1645. /*=============================================*/
  1646. Milestone = 110;
  1647. /*=============================================*/
  1648. printf ("Seeking Underflow thresholds UfThold and E0.\n");
  1649. D = U1;
  1650. if (Precision != FLOOR (Precision))
  1651. {
  1652. D = BInvrse;
  1653. X = Precision;
  1654. do
  1655. {
  1656. D = D * BInvrse;
  1657. X = X - One;
  1658. }
  1659. while (X > Zero);
  1660. }
  1661. Y = One;
  1662. Z = D;
  1663. /* ... D is power of 1/Radix < 1. */
  1664. do
  1665. {
  1666. C = Y;
  1667. Y = Z;
  1668. Z = Y * Y;
  1669. }
  1670. while ((Y > Z) && (Z + Z > Z));
  1671. Y = C;
  1672. Z = Y * D;
  1673. do
  1674. {
  1675. C = Y;
  1676. Y = Z;
  1677. Z = Y * D;
  1678. }
  1679. while ((Y > Z) && (Z + Z > Z));
  1680. if (Radix < Two)
  1681. HInvrse = Two;
  1682. else
  1683. HInvrse = Radix;
  1684. H = One / HInvrse;
  1685. /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
  1686. CInvrse = One / C;
  1687. E0 = C;
  1688. Z = E0 * H;
  1689. /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
  1690. do
  1691. {
  1692. Y = E0;
  1693. E0 = Z;
  1694. Z = E0 * H;
  1695. }
  1696. while ((E0 > Z) && (Z + Z > Z));
  1697. UfThold = E0;
  1698. E1 = Zero;
  1699. Q = Zero;
  1700. E9 = U2;
  1701. S = One + E9;
  1702. D = C * S;
  1703. if (D <= C)
  1704. {
  1705. E9 = Radix * U2;
  1706. S = One + E9;
  1707. D = C * S;
  1708. if (D <= C)
  1709. {
  1710. BadCond (Failure,
  1711. "multiplication gets too many last digits wrong.\n");
  1712. Underflow = E0;
  1713. Y1 = Zero;
  1714. PseudoZero = Z;
  1715. Pause ();
  1716. }
  1717. }
  1718. else
  1719. {
  1720. Underflow = D;
  1721. PseudoZero = Underflow * H;
  1722. UfThold = Zero;
  1723. do
  1724. {
  1725. Y1 = Underflow;
  1726. Underflow = PseudoZero;
  1727. if (E1 + E1 <= E1)
  1728. {
  1729. Y2 = Underflow * HInvrse;
  1730. E1 = FABS (Y1 - Y2);
  1731. Q = Y1;
  1732. if ((UfThold == Zero) && (Y1 != Y2))
  1733. UfThold = Y1;
  1734. }
  1735. PseudoZero = PseudoZero * H;
  1736. }
  1737. while ((Underflow > PseudoZero)
  1738. && (PseudoZero + PseudoZero > PseudoZero));
  1739. }
  1740. /* Comment line 4530 .. 4560 */
  1741. if (PseudoZero != Zero)
  1742. {
  1743. printf ("\n");
  1744. Z = PseudoZero;
  1745. /* ... Test PseudoZero for "phoney- zero" violates */
  1746. /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
  1747. ... */
  1748. if (PseudoZero <= Zero)
  1749. {
  1750. BadCond (Failure, "Positive expressions can underflow to an\n");
  1751. printf ("allegedly negative value\n");
  1752. printf ("PseudoZero that prints out as: %s .\n", PseudoZero.str());
  1753. X = -PseudoZero;
  1754. if (X <= Zero)
  1755. {
  1756. printf ("But -PseudoZero, which should be\n");
  1757. printf ("positive, isn't; it prints out as %s .\n", X.str());
  1758. }
  1759. }
  1760. else
  1761. {
  1762. BadCond (Flaw, "Underflow can stick at an allegedly positive\n");
  1763. printf ("value PseudoZero that prints out as %s .\n",
  1764. PseudoZero.str());
  1765. }
  1766. TstPtUf ();
  1767. }
  1768. /*=============================================*/
  1769. Milestone = 120;
  1770. /*=============================================*/
  1771. if (CInvrse * Y > CInvrse * Y1)
  1772. {
  1773. S = H * S;
  1774. E0 = Underflow;
  1775. }
  1776. if (!((E1 == Zero) || (E1 == E0)))
  1777. {
  1778. BadCond (Defect, "");
  1779. if (E1 < E0)
  1780. {
  1781. printf ("Products underflow at a higher");
  1782. printf (" threshold than differences.\n");
  1783. if (PseudoZero == Zero)
  1784. E0 = E1;
  1785. }
  1786. else
  1787. {
  1788. printf ("Difference underflows at a higher");
  1789. printf (" threshold than products.\n");
  1790. }
  1791. }
  1792. printf ("Smallest strictly positive number found is E0 = %s .\n", E0.str());
  1793. Z = E0;
  1794. TstPtUf ();
  1795. Underflow = E0;
  1796. if (N == 1)
  1797. Underflow = Y;
  1798. I = 4;
  1799. if (E1 == Zero)
  1800. I = 3;
  1801. if (UfThold == Zero)
  1802. I = I - 2;
  1803. UfNGrad = true;
  1804. switch (I)
  1805. {
  1806. case 1:
  1807. UfThold = Underflow;
  1808. if ((CInvrse * Q) != ((CInvrse * Y) * S))
  1809. {
  1810. UfThold = Y;
  1811. BadCond (Failure, "Either accuracy deteriorates as numbers\n");
  1812. printf ("approach a threshold = %s\n", UfThold.str());
  1813. printf (" coming down from %s\n", C.str());
  1814. printf
  1815. (" or else multiplication gets too many last digits wrong.\n");
  1816. }
  1817. Pause ();
  1818. break;
  1819. case 2:
  1820. BadCond (Failure,
  1821. "Underflow confuses Comparison, which alleges that\n");
  1822. printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
  1823. printf ("print out as Q = %s, Y = %s .\n", Q.str(), Y2.str());
  1824. printf ("|Q - Y| = %s .\n", FABS (Q - Y2).str());
  1825. UfThold = Q;
  1826. break;
  1827. case 3:
  1828. X = X;
  1829. break;
  1830. case 4:
  1831. if ((Q == UfThold) && (E1 == E0) && (FABS (UfThold - E1 / E9) <= E1))
  1832. {
  1833. UfNGrad = false;
  1834. printf ("Underflow is gradual; it incurs Absolute Error =\n");
  1835. printf ("(roundoff in UfThold) < E0.\n");
  1836. Y = E0 * CInvrse;
  1837. Y = Y * (OneAndHalf + U2);
  1838. X = CInvrse * (One + U2);
  1839. Y = Y / X;
  1840. IEEE = (Y == E0);
  1841. }
  1842. }
  1843. if (UfNGrad)
  1844. {
  1845. printf ("\n");
  1846. if (setjmp (ovfl_buf))
  1847. {
  1848. printf ("Underflow / UfThold failed!\n");
  1849. R = H + H;
  1850. }
  1851. else
  1852. R = SQRT (Underflow / UfThold);
  1853. if (R <= H)
  1854. {
  1855. Z = R * UfThold;
  1856. X = Z * (One + R * H * (One + H));
  1857. }
  1858. else
  1859. {
  1860. Z = UfThold;
  1861. X = Z * (One + H * H * (One + H));
  1862. }
  1863. if (!((X == Z) || (X - Z != Zero)))
  1864. {
  1865. BadCond (Flaw, "");
  1866. printf ("X = %s\n\tis not equal to Z = %s .\n", X.str(), Z.str());
  1867. Z9 = X - Z;
  1868. printf ("yet X - Z yields %s .\n", Z9.str());
  1869. printf (" Should this NOT signal Underflow, ");
  1870. printf ("this is a SERIOUS DEFECT\nthat causes ");
  1871. printf ("confusion when innocent statements like\n");;
  1872. printf (" if (X == Z) ... else");
  1873. printf (" ... (f(X) - f(Z)) / (X - Z) ...\n");
  1874. printf ("encounter Division by Zero although actually\n");
  1875. if (setjmp (ovfl_buf))
  1876. printf ("X / Z fails!\n");
  1877. else
  1878. printf ("X / Z = 1 + %s .\n", ((X / Z - Half) - Half).str());
  1879. }
  1880. }
  1881. printf ("The Underflow threshold is %s, below which\n", UfThold.str());
  1882. printf ("calculation may suffer larger Relative error than ");
  1883. printf ("merely roundoff.\n");
  1884. Y2 = U1 * U1;
  1885. Y = Y2 * Y2;
  1886. Y2 = Y * U1;
  1887. if (Y2 <= UfThold)
  1888. {
  1889. if (Y > E0)
  1890. {
  1891. BadCond (Defect, "");
  1892. I = 5;
  1893. }
  1894. else
  1895. {
  1896. BadCond (Serious, "");
  1897. I = 4;
  1898. }
  1899. printf ("Range is too narrow; U1^%d Underflows.\n", I);
  1900. }
  1901. /*=============================================*/
  1902. Milestone = 130;
  1903. /*=============================================*/
  1904. Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty;
  1905. Y2 = Y + Y;
  1906. printf ("Since underflow occurs below the threshold\n");
  1907. printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse.str(), Y.str());
  1908. printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
  1909. HInvrse.str(), Y2.str());
  1910. printf ("actually calculating yields:");
  1911. if (setjmp (ovfl_buf))
  1912. {
  1913. BadCond (Serious, "trap on underflow.\n");
  1914. }
  1915. else
  1916. {
  1917. V9 = POW (HInvrse, Y2);
  1918. printf (" %s .\n", V9.str());
  1919. if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold)))
  1920. {
  1921. BadCond (Serious, "this is not between 0 and underflow\n");
  1922. printf (" threshold = %s .\n", UfThold.str());
  1923. }
  1924. else if (!(V9 > UfThold * (One + E9)))
  1925. printf ("This computed value is O.K.\n");
  1926. else
  1927. {
  1928. BadCond (Defect, "this is not between 0 and underflow\n");
  1929. printf (" threshold = %s .\n", UfThold.str());
  1930. }
  1931. }
  1932. /*=============================================*/
  1933. Milestone = 160;
  1934. /*=============================================*/
  1935. Pause ();
  1936. printf ("Searching for Overflow threshold:\n");
  1937. printf ("This may generate an error.\n");
  1938. Y = -CInvrse;
  1939. V9 = HInvrse * Y;
  1940. if (setjmp (ovfl_buf))
  1941. {
  1942. I = 0;
  1943. V9 = Y;
  1944. goto overflow;
  1945. }
  1946. do
  1947. {
  1948. V = Y;
  1949. Y = V9;
  1950. V9 = HInvrse * Y;
  1951. }
  1952. while (V9 < Y);
  1953. I = 1;
  1954. overflow:
  1955. Z = V9;
  1956. printf ("Can `Z = -Y' overflow?\n");
  1957. printf ("Trying it on Y = %s .\n", Y.str());
  1958. V9 = -Y;
  1959. V0 = V9;
  1960. if (V - Y == V + V0)
  1961. printf ("Seems O.K.\n");
  1962. else
  1963. {
  1964. printf ("finds a ");
  1965. BadCond (Flaw, "-(-Y) differs from Y.\n");
  1966. }
  1967. if (Z != Y)
  1968. {
  1969. BadCond (Serious, "");
  1970. printf ("overflow past %s\n\tshrinks to %s .\n", Y.str(), Z.str());
  1971. }
  1972. if (I)
  1973. {
  1974. Y = V * (HInvrse * U2 - HInvrse);
  1975. Z = Y + ((One - HInvrse) * U2) * V;
  1976. if (Z < V0)
  1977. Y = Z;
  1978. if (Y < V0)
  1979. V = Y;
  1980. if (V0 - V < V0)
  1981. V = V0;
  1982. }
  1983. else
  1984. {
  1985. V = Y * (HInvrse * U2 - HInvrse);
  1986. V = V + ((One - HInvrse) * U2) * Y;
  1987. }
  1988. printf ("Overflow threshold is V = %s .\n", V.str());
  1989. if (I)
  1990. printf ("Overflow saturates at V0 = %s .\n", V0.str());
  1991. else
  1992. printf ("There is no saturation value because "
  1993. "the system traps on overflow.\n");
  1994. V9 = V * One;
  1995. printf ("No Overflow should be signaled for V * 1 = %s\n", V9.str());
  1996. V9 = V / One;
  1997. printf (" nor for V / 1 = %s.\n", V9.str());
  1998. printf ("Any overflow signal separating this * from the one\n");
  1999. printf ("above is a DEFECT.\n");
  2000. /*=============================================*/
  2001. Milestone = 170;
  2002. /*=============================================*/
  2003. if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V))
  2004. {
  2005. BadCond (Failure, "Comparisons involving ");
  2006. printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
  2007. V.str(), V0.str(), UfThold.str());
  2008. }
  2009. /*=============================================*/
  2010. Milestone = 175;
  2011. /*=============================================*/
  2012. printf ("\n");
  2013. for (Indx = 1; Indx <= 3; ++Indx)
  2014. {
  2015. switch (Indx)
  2016. {
  2017. case 1:
  2018. Z = UfThold;
  2019. break;
  2020. case 2:
  2021. Z = E0;
  2022. break;
  2023. case 3:
  2024. Z = PseudoZero;
  2025. break;
  2026. }
  2027. if (Z != Zero)
  2028. {
  2029. V9 = SQRT (Z);
  2030. Y = V9 * V9;
  2031. if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z)
  2032. { /* dgh: + E9 --> * E9 */
  2033. if (V9 > U1)
  2034. BadCond (Serious, "");
  2035. else
  2036. BadCond (Defect, "");
  2037. printf ("Comparison alleges that what prints as Z = %s\n",
  2038. Z.str());
  2039. printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y.str());
  2040. }
  2041. }
  2042. }
  2043. /*=============================================*/
  2044. Milestone = 180;
  2045. /*=============================================*/
  2046. for (Indx = 1; Indx <= 2; ++Indx)
  2047. {
  2048. if (Indx == 1)
  2049. Z = V;
  2050. else
  2051. Z = V0;
  2052. V9 = SQRT (Z);
  2053. X = (One - Radix * E9) * V9;
  2054. V9 = V9 * X;
  2055. if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z)))
  2056. {
  2057. Y = V9;
  2058. if (X < W)
  2059. BadCond (Serious, "");
  2060. else
  2061. BadCond (Defect, "");
  2062. printf ("Comparison alleges that Z = %s\n", Z.str());
  2063. printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y.str());
  2064. }
  2065. }
  2066. /*=============================================*/
  2067. Milestone = 190;
  2068. /*=============================================*/
  2069. Pause ();
  2070. X = UfThold * V;
  2071. Y = Radix * Radix;
  2072. if (X * Y < One || X > Y)
  2073. {
  2074. if (X * Y < U1 || X > Y / U1)
  2075. BadCond (Defect, "Badly");
  2076. else
  2077. BadCond (Flaw, "");
  2078. printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
  2079. X.str(), "is too far from 1.\n");
  2080. }
  2081. /*=============================================*/
  2082. Milestone = 200;
  2083. /*=============================================*/
  2084. for (Indx = 1; Indx <= 5; ++Indx)
  2085. {
  2086. X = F9;
  2087. switch (Indx)
  2088. {
  2089. case 2:
  2090. X = One + U2;
  2091. break;
  2092. case 3:
  2093. X = V;
  2094. break;
  2095. case 4:
  2096. X = UfThold;
  2097. break;
  2098. case 5:
  2099. X = Radix;
  2100. }
  2101. Y = X;
  2102. if (setjmp (ovfl_buf))
  2103. printf (" X / X traps when X = %s\n", X.str());
  2104. else
  2105. {
  2106. V9 = (Y / X - Half) - Half;
  2107. if (V9 == Zero)
  2108. continue;
  2109. if (V9 == -U1 && Indx < 5)
  2110. BadCond (Flaw, "");
  2111. else
  2112. BadCond (Serious, "");
  2113. printf (" X / X differs from 1 when X = %s\n", X.str());
  2114. printf (" instead, X / X - 1/2 - 1/2 = %s .\n", V9.str());
  2115. }
  2116. }
  2117. /*=============================================*/
  2118. Milestone = 210;
  2119. /*=============================================*/
  2120. MyZero = Zero;
  2121. printf ("\n");
  2122. printf ("What message and/or values does Division by Zero produce?\n");
  2123. printf (" Trying to compute 1 / 0 produces ...");
  2124. if (!setjmp (ovfl_buf))
  2125. printf (" %s .\n", (One / MyZero).str());
  2126. printf ("\n Trying to compute 0 / 0 produces ...");
  2127. if (!setjmp (ovfl_buf))
  2128. printf (" %s .\n", (Zero / MyZero).str());
  2129. /*=============================================*/
  2130. Milestone = 220;
  2131. /*=============================================*/
  2132. Pause ();
  2133. printf ("\n");
  2134. {
  2135. static const char *msg[] = {
  2136. "FAILUREs encountered =",
  2137. "SERIOUS DEFECTs discovered =",
  2138. "DEFECTs discovered =",
  2139. "FLAWs discovered ="
  2140. };
  2141. int i;
  2142. for (i = 0; i < 4; i++)
  2143. if (ErrCnt[i])
  2144. printf ("The number of %-29s %d.\n", msg[i], ErrCnt[i]);
  2145. }
  2146. printf ("\n");
  2147. if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0)
  2148. {
  2149. if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] == 0)
  2150. && (ErrCnt[Flaw] > 0))
  2151. {
  2152. printf ("The arithmetic diagnosed seems ");
  2153. printf ("Satisfactory though flawed.\n");
  2154. }
  2155. if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && (ErrCnt[Defect] > 0))
  2156. {
  2157. printf ("The arithmetic diagnosed may be Acceptable\n");
  2158. printf ("despite inconvenient Defects.\n");
  2159. }
  2160. if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0)
  2161. {
  2162. printf ("The arithmetic diagnosed has ");
  2163. printf ("unacceptable Serious Defects.\n");
  2164. }
  2165. if (ErrCnt[Failure] > 0)
  2166. {
  2167. printf ("Potentially fatal FAILURE may have spoiled this");
  2168. printf (" program's subsequent diagnoses.\n");
  2169. }
  2170. }
  2171. else
  2172. {
  2173. printf ("No failures, defects nor flaws have been discovered.\n");
  2174. if (!((RMult == Rounded) && (RDiv == Rounded)
  2175. && (RAddSub == Rounded) && (RSqrt == Rounded)))
  2176. printf ("The arithmetic diagnosed seems Satisfactory.\n");
  2177. else
  2178. {
  2179. if (StickyBit >= One &&
  2180. (Radix - Two) * (Radix - Nine - One) == Zero)
  2181. {
  2182. printf ("Rounding appears to conform to ");
  2183. printf ("the proposed IEEE standard P");
  2184. if ((Radix == Two) &&
  2185. ((Precision - Four * Three * Two) *
  2186. (Precision - TwentySeven - TwentySeven + One) == Zero))
  2187. printf ("754");
  2188. else
  2189. printf ("854");
  2190. if (IEEE)
  2191. printf (".\n");
  2192. else
  2193. {
  2194. printf (",\nexcept for possibly Double Rounding");
  2195. printf (" during Gradual Underflow.\n");
  2196. }
  2197. }
  2198. printf ("The arithmetic diagnosed appears to be Excellent!\n");
  2199. }
  2200. }
  2201. printf ("END OF TEST.\n");
  2202. return 0;
  2203. }
  2204. template<typename FLOAT>
  2205. FLOAT
  2206. Paranoia<FLOAT>::Sign (FLOAT X)
  2207. {
  2208. return X >= FLOAT (long (0)) ? 1 : -1;
  2209. }
  2210. template<typename FLOAT>
  2211. void
  2212. Paranoia<FLOAT>::Pause ()
  2213. {
  2214. if (do_pause)
  2215. {
  2216. fputs ("Press return...", stdout);
  2217. fflush (stdout);
  2218. getchar();
  2219. }
  2220. printf ("\nDiagnosis resumes after milestone Number %d", Milestone);
  2221. printf (" Page: %d\n\n", PageNo);
  2222. ++Milestone;
  2223. ++PageNo;
  2224. }
  2225. template<typename FLOAT>
  2226. void
  2227. Paranoia<FLOAT>::TstCond (int K, int Valid, const char *T)
  2228. {
  2229. if (!Valid)
  2230. {
  2231. BadCond (K, T);
  2232. printf (".\n");
  2233. }
  2234. }
  2235. template<typename FLOAT>
  2236. void
  2237. Paranoia<FLOAT>::BadCond (int K, const char *T)
  2238. {
  2239. static const char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
  2240. ErrCnt[K] = ErrCnt[K] + 1;
  2241. printf ("%s: %s", msg[K], T);
  2242. }
  2243. /* Random computes
  2244. X = (Random1 + Random9)^5
  2245. Random1 = X - FLOOR(X) + 0.000005 * X;
  2246. and returns the new value of Random1. */
  2247. template<typename FLOAT>
  2248. FLOAT
  2249. Paranoia<FLOAT>::Random ()
  2250. {
  2251. FLOAT X, Y;
  2252. X = Random1 + Random9;
  2253. Y = X * X;
  2254. Y = Y * Y;
  2255. X = X * Y;
  2256. Y = X - FLOOR (X);
  2257. Random1 = Y + X * FLOAT ("0.000005");
  2258. return (Random1);
  2259. }
  2260. template<typename FLOAT>
  2261. void
  2262. Paranoia<FLOAT>::SqXMinX (int ErrKind)
  2263. {
  2264. FLOAT XA, XB;
  2265. XB = X * BInvrse;
  2266. XA = X - XB;
  2267. SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp;
  2268. if (SqEr != Zero)
  2269. {
  2270. if (SqEr < MinSqEr)
  2271. MinSqEr = SqEr;
  2272. if (SqEr > MaxSqEr)
  2273. MaxSqEr = SqEr;
  2274. J = J + 1;
  2275. BadCond (ErrKind, "\n");
  2276. printf ("sqrt(%s) - %s = %s\n", (X * X).str(), X.str(),
  2277. (OneUlp * SqEr).str());
  2278. printf ("\tinstead of correct value 0 .\n");
  2279. }
  2280. }
  2281. template<typename FLOAT>
  2282. void
  2283. Paranoia<FLOAT>::NewD ()
  2284. {
  2285. X = Z1 * Q;
  2286. X = FLOOR (Half - X / Radix) * Radix + X;
  2287. Q = (Q - X * Z) / Radix + X * X * (D / Radix);
  2288. Z = Z - Two * X * D;
  2289. if (Z <= Zero)
  2290. {
  2291. Z = -Z;
  2292. Z1 = -Z1;
  2293. }
  2294. D = Radix * D;
  2295. }
  2296. template<typename FLOAT>
  2297. void
  2298. Paranoia<FLOAT>::SR3750 ()
  2299. {
  2300. if (!((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2)))
  2301. {
  2302. I = I + 1;
  2303. X2 = SQRT (X * D);
  2304. Y2 = (X2 - Z2) - (Y - Z2);
  2305. X2 = X8 / (Y - Half);
  2306. X2 = X2 - Half * X2 * X2;
  2307. SqEr = (Y2 + Half) + (Half - X2);
  2308. if (SqEr < MinSqEr)
  2309. MinSqEr = SqEr;
  2310. SqEr = Y2 - X2;
  2311. if (SqEr > MaxSqEr)
  2312. MaxSqEr = SqEr;
  2313. }
  2314. }
  2315. template<typename FLOAT>
  2316. void
  2317. Paranoia<FLOAT>::IsYeqX ()
  2318. {
  2319. if (Y != X)
  2320. {
  2321. if (N <= 0)
  2322. {
  2323. if (Z == Zero && Q <= Zero)
  2324. printf ("WARNING: computing\n");
  2325. else
  2326. BadCond (Defect, "computing\n");
  2327. printf ("\t(%s) ^ (%s)\n", Z.str(), Q.str());
  2328. printf ("\tyielded %s;\n", Y.str());
  2329. printf ("\twhich compared unequal to correct %s ;\n", X.str());
  2330. printf ("\t\tthey differ by %s .\n", (Y - X).str());
  2331. }
  2332. N = N + 1; /* ... count discrepancies. */
  2333. }
  2334. }
  2335. template<typename FLOAT>
  2336. void
  2337. Paranoia<FLOAT>::PrintIfNPositive ()
  2338. {
  2339. if (N > 0)
  2340. printf ("Similar discrepancies have occurred %d times.\n", N);
  2341. }
  2342. template<typename FLOAT>
  2343. void
  2344. Paranoia<FLOAT>::TstPtUf ()
  2345. {
  2346. N = 0;
  2347. if (Z != Zero)
  2348. {
  2349. printf ("Since comparison denies Z = 0, evaluating ");
  2350. printf ("(Z + Z) / Z should be safe.\n");
  2351. if (setjmp (ovfl_buf))
  2352. goto very_serious;
  2353. Q9 = (Z + Z) / Z;
  2354. printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9.str());
  2355. if (FABS (Q9 - Two) < Radix * U2)
  2356. {
  2357. printf ("This is O.K., provided Over/Underflow");
  2358. printf (" has NOT just been signaled.\n");
  2359. }
  2360. else
  2361. {
  2362. if ((Q9 < One) || (Q9 > Two))
  2363. {
  2364. very_serious:
  2365. N = 1;
  2366. ErrCnt[Serious] = ErrCnt[Serious] + 1;
  2367. printf ("This is a VERY SERIOUS DEFECT!\n");
  2368. }
  2369. else
  2370. {
  2371. N = 1;
  2372. ErrCnt[Defect] = ErrCnt[Defect] + 1;
  2373. printf ("This is a DEFECT!\n");
  2374. }
  2375. }
  2376. V9 = Z * One;
  2377. Random1 = V9;
  2378. V9 = One * Z;
  2379. Random2 = V9;
  2380. V9 = Z / One;
  2381. if ((Z == Random1) && (Z == Random2) && (Z == V9))
  2382. {
  2383. if (N > 0)
  2384. Pause ();
  2385. }
  2386. else
  2387. {
  2388. N = 1;
  2389. BadCond (Defect, "What prints as Z = ");
  2390. printf ("%s\n\tcompares different from ", Z.str());
  2391. if (Z != Random1)
  2392. printf ("Z * 1 = %s ", Random1.str());
  2393. if (!((Z == Random2) || (Random2 == Random1)))
  2394. printf ("1 * Z == %s\n", Random2.str());
  2395. if (!(Z == V9))
  2396. printf ("Z / 1 = %s\n", V9.str());
  2397. if (Random2 != Random1)
  2398. {
  2399. ErrCnt[Defect] = ErrCnt[Defect] + 1;
  2400. BadCond (Defect, "Multiplication does not commute!\n");
  2401. printf ("\tComparison alleges that 1 * Z = %s\n", Random2.str());
  2402. printf ("\tdiffers from Z * 1 = %s\n", Random1.str());
  2403. }
  2404. Pause ();
  2405. }
  2406. }
  2407. }
  2408. template<typename FLOAT>
  2409. void
  2410. Paranoia<FLOAT>::notify (const char *s)
  2411. {
  2412. printf ("%s test appears to be inconsistent...\n", s);
  2413. printf (" PLEASE NOTIFY KARPINKSI!\n");
  2414. }
  2415. /* ====================================================================== */
  2416. int main(int ac, char **av)
  2417. {
  2418. setbuf(stdout, NULL);
  2419. setbuf(stderr, NULL);
  2420. while (1)
  2421. switch (getopt (ac, av, "pvg:fdl"))
  2422. {
  2423. case -1:
  2424. return 0;
  2425. case 'p':
  2426. do_pause = true;
  2427. break;
  2428. case 'v':
  2429. verbose = true;
  2430. break;
  2431. case 'g':
  2432. {
  2433. static const struct {
  2434. const char *name;
  2435. const struct real_format *fmt;
  2436. } fmts[] = {
  2437. #define F(x) { #x, &x##_format }
  2438. F(ieee_single),
  2439. F(ieee_double),
  2440. F(ieee_extended_motorola),
  2441. F(ieee_extended_intel_96),
  2442. F(ieee_extended_intel_128),
  2443. F(ibm_extended),
  2444. F(ieee_quad),
  2445. F(vax_f),
  2446. F(vax_d),
  2447. F(vax_g),
  2448. F(i370_single),
  2449. F(i370_double),
  2450. F(real_internal),
  2451. #undef F
  2452. };
  2453. int i, n = sizeof (fmts)/sizeof(*fmts);
  2454. for (i = 0; i < n; ++i)
  2455. if (strcmp (fmts[i].name, optarg) == 0)
  2456. break;
  2457. if (i == n)
  2458. {
  2459. printf ("Unknown implementation \"%s\"; "
  2460. "available implementations:\n", optarg);
  2461. for (i = 0; i < n; ++i)
  2462. printf ("\t%s\n", fmts[i].name);
  2463. return 1;
  2464. }
  2465. // We cheat and use the same mode all the time, but vary
  2466. // the format used for that mode.
  2467. real_format_for_mode[int(real_c_float::MODE) - int(QFmode)]
  2468. = fmts[i].fmt;
  2469. Paranoia<real_c_float>().main();
  2470. break;
  2471. }
  2472. case 'f':
  2473. Paranoia < native_float<float> >().main();
  2474. break;
  2475. case 'd':
  2476. Paranoia < native_float<double> >().main();
  2477. break;
  2478. case 'l':
  2479. #ifndef NO_LONG_DOUBLE
  2480. Paranoia < native_float<long double> >().main();
  2481. #endif
  2482. break;
  2483. case '?':
  2484. puts ("-p\tpause between pages");
  2485. puts ("-g<FMT>\treal.c implementation FMT");
  2486. puts ("-f\tnative float");
  2487. puts ("-d\tnative double");
  2488. puts ("-l\tnative long double");
  2489. return 0;
  2490. }
  2491. }
  2492. /* GCC stuff referenced by real.o. */
  2493. extern "C" void
  2494. fancy_abort ()
  2495. {
  2496. abort ();
  2497. }
  2498. int target_flags = 0;
  2499. extern "C" int
  2500. floor_log2_wide (unsigned HOST_WIDE_INT x)
  2501. {
  2502. int log = -1;
  2503. while (x != 0)
  2504. log++,
  2505. x >>= 1;
  2506. return log;
  2507. }