├── LICENSE ├── README.md ├── doc ├── cbench.bib ├── cbench.tex └── sqrt_approx.ps └── src ├── cat ├── cat1.c ├── cat2.c └── cat3.c ├── fac ├── fac1.c ├── fac2.c ├── fac3.c ├── fac4.c ├── fac5.c ├── fac6.c ├── facx.c └── facy.c ├── malloc ├── malloc1.c ├── malloc2.c ├── malloc3.c └── malloc4.c ├── qsort ├── qsort1.c ├── qsort2.c ├── qsort3.c ├── qsort4.c └── qsort5.c └── sqrt ├── sqrt1.c ├── sqrt2.c ├── sqrt3.c ├── sqrt4.c └── sqrtsf2.c /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Here is a challenge for people who are interested in practical C program verification using formal methods. Show us how to verify the correctness of the twenty-five programs in the paper [A benchmark for C program verification](https://arxiv.org/abs/1904.01009). 2 | 3 | If you are interested in this in any way, feel free to send mail (and preferably verification proofs of these programs) to freek@cs.ru.nl. 4 | 5 | Points scored on the benchmark thus far (that we are aware of): 6 | 7 | | | [VeriFast](https://github.com/verifast/verifast) | [VST](https://vst.cs.princeton.edu) | 8 | |-------------|----:|----:| 9 | | **Total** | 4 | 50 | 10 | | `fac1.c` | 4 | 4 | 11 | | `fac2.c` | | 4 | 12 | | `fac3.c` | | 4 | 13 | | `fac4.c` | | 4 | 14 | | `fac6.c` | | 4 | 15 | | `cat1.c` | | 4 | 16 | | `cat2.c` | | 4 | 17 | | `malloc1.c` | | 4 | 18 | | `qsort1.c` | | 4 | 19 | | `qsort3.c` | | 4 | 20 | | `qsort4.c` | | 3 | 21 | | `sqrt1.c` | | 4 | 22 | | `sqrt3.c` | | 3 | 23 | 24 | The verifications are in the repositories [cbench-verifast](https://github.com/cverified/cbench-verifast) and [cbench-vst](https://github.com/cverified/cbench-vst). 25 | -------------------------------------------------------------------------------- /doc/cbench.bib: -------------------------------------------------------------------------------- 1 | @misc{xxx, 2 | author={xxx}, 3 | title={xxx}, 4 | year=2019 5 | } 6 | 7 | @inproceedings{jac:sma:phi:vog:pen:pie:11, 8 | author = {Jacobs, Bart and Smans, Jan and Philippaerts, Pieter and Vogels, Fr{\'e}d{\'e}ric and Penninckx, Willem and Piessens, Frank}, 9 | title = "{VeriFast: A Powerful, Sound, Predictable, Fast Verifier for C and Java}", 10 | booktitle = "{Proceedings of the Third International Conference on NASA Formal Methods}", 11 | series = {NFM'11}, 12 | year = {2011}, 13 | isbn = {978-3-642-20397-8}, 14 | location = {Pasadena, CA}, 15 | pages = {41--55}, 16 | numpages = {15}, 17 | url = {http://dl.acm.org/citation.cfm?id=1986308.1986314}, 18 | acmid = {1986314}, 19 | publisher = {Springer-Verlag}, 20 | address = {Berlin, Heidelberg}, 21 | } 22 | 23 | @inproceedings{dah:mos:san:tob:sch:09, 24 | author = {Markus Dahlweid and 25 | Michal Moskal and 26 | Thomas Santen and 27 | Stephan Tobies and 28 | Wolfram Schulte}, 29 | title = "{{VCC:} Contract-based modular verification of concurrent {C}}", 30 | booktitle = "{31st International Conference on Software Engineering, {ICSE} 2009, 31 | May 16-24, 2009, Vancouver, Canada, Companion Volume}", 32 | pages = {429--430}, 33 | year = {2009}, 34 | url = {https://doi.org/10.1109/ICSE-COMPANION.2009.5071046}, 35 | doi = {10.1109/ICSE-COMPANION.2009.5071046}, 36 | timestamp = {Tue, 23 May 2017 01:11:51 +0200}, 37 | biburl = {http://dblp.uni-trier.de/rec/bib/conf/icse/DahlweidMSTS09}, 38 | bibsource = {dblp computer science bibliography, http://dblp.org}, 39 | publisher = {{IEEE}}, 40 | isbn = {978-1-4244-3494-7}, 41 | timestamp = {Tue, 16 Jun 2009 14:53:25 +0200}, 42 | } 43 | 44 | @inproceedings{gre:and:klei:12, 45 | author="Greenaway, David 46 | and Andronick, June 47 | and Klein, Gerwin", 48 | editor="Beringer, Lennart 49 | and Felty, Amy", 50 | title="{Bridging the Gap: Automatic Verified Abstraction of C}", 51 | bookTitle="Interactive Theorem Proving: Third International Conference, ITP 2012, Princeton, NJ, USA, August 13-15, 2012. Proceedings", 52 | year="2012", 53 | publisher="Springer Berlin Heidelberg", 54 | address="Berlin, Heidelberg", 55 | pages="99--115", 56 | abstract="Before low-level imperative code can be reasoned about in an interactive theorem prover, it must first be converted into a logical representation in that theorem prover. Accurate translations of such code should be conservative, choosing safe representations over representations convenient to reason about. This paper bridges the gap between conservative representation and convenient reasoning. We present a tool that automatically abstracts low-level C semantics into higher level specifications, while generating proofs of refinement in Isabelle/HOL for each translation step. The aim is to generate a verified, human-readable specification, convenient for further reasoning.", 57 | isbn="978-3-642-32347-8", 58 | doi="10.1007/978-3-642-32347-8_8", 59 | url="http://dx.doi.org/10.1007/978-3-642-32347-8_8" 60 | } 61 | 62 | @inproceedings{app:11, 63 | author = {Appel, Andrew W.}, 64 | title = {Verified software toolchain}, 65 | booktitle = {Proceedings of the 20th European Symposium on Programming}, 66 | series = {ESOP'11/ETAPS'11}, 67 | year = {2011}, 68 | location = {Saarbr\&\#252;cken, Germany}, 69 | pages = {1--17}, 70 | url = {http://dl.acm.org/citation.cfm?id=1987211.1987212}, 71 | } 72 | 73 | @inproceedings{mar:07, 74 | author = {March{\'e}, Claude}, 75 | title = {Jessie: An Intermediate Language for Java and C Verification}, 76 | booktitle = {Proceedings of the 2007 Workshop on Programming Languages Meets Program Verification}, 77 | series = {PLPV '07}, 78 | year = {2007}, 79 | isbn = {978-1-59593-677-6}, 80 | location = {Freiburg, Germany}, 81 | pages = {1--2}, 82 | numpages = {2}, 83 | url = {http://doi.acm.org/10.1145/1292597.1292598}, 84 | doi = {10.1145/1292597.1292598}, 85 | acmid = {1292598}, 86 | publisher = {ACM}, 87 | address = {New York, NY, USA}, 88 | keywords = {behavioral properties, verification, verification conditions generator}, 89 | } 90 | 91 | @misc{eek:geu:sme:wie:14, 92 | author = {Eekelen, M.C.J.D. van and J.H. Geuvers and J.E.W. Smetsers and F. Wiedijk}, 93 | title = "{SOVEREIGN: A Framework for Modular Formal Verification of Safety Critical Software, 94 | STW OTP-project proposal}", 95 | year = 2014 96 | } 97 | 98 | @incollection{sta:02, 99 | added-at = {2014-12-29T19:15:00.000+0100}, 100 | address = {Boston}, 101 | author = {Stallman, Richard M.}, 102 | biburl = {http://www.bibsonomy.org/bibtex/22a1d540e299a4b5d27c304a1f0d5d305/jsiltala}, 103 | booktitle = {Free {S}oftware, {F}ree {S}ociety: {S}elected {E}ssays of {R}ichard {M}. {S}tallman}, 104 | editor = {Gay, Joshua}, 105 | interhash = {27bec104b39e6c6019564ffe6692fb3a}, 106 | intrahash = {2a1d540e299a4b5d27c304a1f0d5d305}, 107 | keywords = {imported}, 108 | owner = {juha}, 109 | pages = {33-41}, 110 | publisher = {GNU Press}, 111 | timestamp = {2015-01-02T12:38:53.000+0100}, 112 | title = {The {GNU} {M}anifesto}, 113 | year = 2002 114 | } 115 | 116 | @manual{bau:cuo:fil:mar:mon:moy:pre:16, 117 | title = "{ACSL: ANSI/ISO C Specification Language, version 1.12}", 118 | author = {Patrick Baudin and Pascal Cuoq and Jean-Christophe Filli\^atre and Claude March\'e and Benjamin Monate and Yannick Moy and Virgile Prevosto}, 119 | year = 2016, 120 | note = {\url{https://frama-c.com/acsl.html}}, 121 | url = {https://frama-c.com/acsl.html} 122 | } 123 | 124 | @book{iso:11, 125 | added-at = {2012-10-08T01:11:26.000+0200}, 126 | address = {Geneva, Switzerland}, 127 | author = {{ISO}}, 128 | bibdate = {Mon Dec 19 11:12:12 2011}, 129 | bibsource = {http://www.math.utah.edu/pub/tex/bib/isostd.bib}, 130 | biburl = {https://www.bibsonomy.org/bibtex/264bc1cf4b2d3d46315a953c6f1688352/gron}, 131 | day = 8, 132 | interhash = {c06a7dbbcb6724820875e51543282440}, 133 | intrahash = {64bc1cf4b2d3d46315a953c6f1688352}, 134 | keywords = {C Specification Standard}, 135 | month = {December}, 136 | pages = {683 (est.)}, 137 | publisher = {International Organization for Standardization}, 138 | remark = {Revises ISO/IEC 9899:1999, ISO/IEC 9899:1999/Cor 139 | 1:2001, ISO/IEC 9899:1999/Cor 2:2004, and ISO/IEC 140 | 9899:1999/Cor 3:2007.}, 141 | timestamp = {2012-10-08T01:11:26.000+0200}, 142 | title = {{ISO/IEC 9899:2011 Information technology --- 143 | Programming languages --- C}}, 144 | url = {http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853}, 145 | year = 2011 146 | } 147 | 148 | @inproceedings{tur:49, 149 | title = "{Checking a large routine}", 150 | author = "Alan Turing", 151 | booktitle = "{Report of a Conference on High Speed Automatic Calculating Machines}", 152 | publisher = "University Mathematical Laboratory, Cambridge", 153 | pages = "67--69", 154 | note = "\url{http://www.turingarchive.org/browse.php/b/8}", 155 | year = 1949 156 | } 157 | 158 | @inproceedings{wie:16, 159 | title = "{A large routine}", 160 | author = "Freek Wiedijk", 161 | booktitle = "Liber Amicorum voor / for Jan A. Bergstra", 162 | editor = "Inge Bethke and Bert Bredeweg and Alban Ponse", 163 | publisher = "Informatics Institute, University of Amsterdam", 164 | pages = "162--163", 165 | note = "\url{http://www.cs.ru.nl/~freek/pilot/janb.pdf}", 166 | year = 2016 167 | } 168 | 169 | @manual{gra:16, 170 | title = "{GNU MP, The GNU Multiple Precision Arithmetic Library, Edition 6.1.1}", 171 | author = "Granlund, {Torbj\"orn} and the GMP development team", 172 | year = 2016 173 | } 174 | 175 | @phdthesis{kre:15, 176 | title = "{The C standard formalized in Coq}", 177 | author = "Robbert Krebbers", 178 | school = "Radboud University Nijmegen", 179 | year = 2015 180 | } 181 | 182 | @inproceedings{ben:06, 183 | author = {Nick Benton}, 184 | title = "{Abstracting Allocation, The New new thing}", 185 | booktitle = {Computer Science Logic, 20th International Workshop, {CSL} 2006, 15th 186 | Annual Conference of the EACSL, Szeged, Hungary, September 25-29, 187 | 2006, Proceedings}, 188 | pages = {182--196}, 189 | year = {2006}, 190 | url = {https://doi.org/10.1007/11874683_12}, 191 | doi = {10.1007/11874683_12}, 192 | timestamp = {Fri, 02 Jun 2017 13:01:07 +0200}, 193 | biburl = {http://dblp.uni-trier.de/rec/bib/conf/csl/Benton06}, 194 | bibsource = {dblp computer science bibliography, http://dblp.org} 195 | } 196 | 197 | @inproceedings{ben:06:1, 198 | author = {Nick Benton}, 199 | title = "{Machine Obstructed Proof: How many months can it take to verify 30 assembly instructions?}", 200 | booktitle = {Workshop on Mechanizing Metatheory}, 201 | year = 2006, 202 | } 203 | 204 | @article{kre:16, 205 | author = {Robbert Krebbers}, 206 | title = {A Formal {C} Memory Model for Separation Logic}, 207 | journal = {J. Autom. Reasoning}, 208 | volume = {57}, 209 | number = {4}, 210 | pages = {319--387}, 211 | year = {2016}, 212 | url = {https://doi.org/10.1007/s10817-016-9369-1}, 213 | doi = {10.1007/s10817-016-9369-1}, 214 | timestamp = {Sat, 20 May 2017 00:22:31 +0200}, 215 | biburl = {http://dblp.uni-trier.de/rec/bib/journals/jar/Krebbers16}, 216 | bibsource = {dblp computer science bibliography, http://dblp.org} 217 | } 218 | 219 | @article{bli:97, 220 | author = {Blinn, James F.}, 221 | title = {Floating-point Tricks}, 222 | journal = {IEEE Comput. Graph. Appl.}, 223 | issue_date = {July 1997}, 224 | volume = {17}, 225 | number = {4}, 226 | month = jul, 227 | year = {1997}, 228 | issn = {0272-1716}, 229 | pages = {80--84}, 230 | numpages = {5}, 231 | url = {http://dx.doi.org/10.1109/38.595279}, 232 | doi = {10.1109/38.595279}, 233 | acmid = {2295790}, 234 | publisher = {IEEE Computer Society Press}, 235 | address = {Los Alamitos, CA, USA}, 236 | } 237 | 238 | @misc{wie:16:1, 239 | author = {Freek Wiedijk}, 240 | title = "{Verifying SHA using VST}", 241 | note = "slides for the course Type Theory \& Coq 2015-2016, Radboud University Nijmegen, \url{http://www.cs.ru.nl/~freek/talks/vst-sha.pdf}.", 242 | year = 2016 243 | } 244 | 245 | @inproceedings{gun:myr:kum:nor:17, 246 | author = {Gu\'eneau, Arma\"el and Myreen, Magnus and Kumar, Ramana and Norrish, Michael}, 247 | month = apr, 248 | year = {2017}, 249 | title = {Verified Characteristic Formulae for {CakeML}}, 250 | booktitle = {European Symposium on Programming}, 251 | pages = {584-610}, 252 | address = {Uppsala, Sweden} 253 | } 254 | 255 | @article{hoa:61, 256 | author = "Hoare, C. A. R.", 257 | title = "{Algorithm 63: Partition and Algorithm 64: Quicksort}", 258 | journal = "Communications of the ACM", 259 | volume = "4", 260 | number = "7", 261 | pages = "321", 262 | year = 1961 263 | } 264 | 265 | @techreport{lei:mos:10, 266 | author = "Leino, K. Rustan M. and Moskal, Micha{\l}", 267 | title = "{VACID-0: Verification of Ample Correctness of Invariants of Data-structures, Edition 0}", 268 | institution = "Microsoft Research, Redmond, WA, USA", 269 | number = "KRML 209", 270 | year = 2010 271 | } 272 | 273 | @manual{cor:cuo:kir:mar:pre:puc:sig:yak:18, 274 | author = "Lo{\"i}c Correnson and Pascal Cuoq and Florent Kirchner and Andr{\'e} Maroneze and Virgile Prevosto and Armand Puccetti and Julien Signoles and Boris Yakobowski", 275 | title = "{Frama-C User Manual}", 276 | year = 2018 277 | } 278 | 279 | @inproceedings{kle:mul:sha:lea:wus:alk:art:bro:cha:coh:hil:jac:lei:mon:pie:pol:rid:sma:tob:tue:ulb:wei:11, 280 | author = {Vladimir Klebanov and 281 | Peter M{\"u}ller and 282 | Natarajan Shankar and 283 | Gary T. Leavens and 284 | Valentin W{\"u}stholz and 285 | Eyad Alkassar and 286 | Rob Arthan and 287 | Derek Bronish and 288 | Rod Chapman and 289 | Ernie Cohen and 290 | Mark Hillebrand and 291 | Bart Jacobs and 292 | K. Rustan M. Leino and 293 | Rosemary Monahan and 294 | Frank Piessens and 295 | Nadia Polikarpova and 296 | Tom Ridge and 297 | Jan Smans and 298 | Stephan Tobies and 299 | Thomas Tuerk and 300 | Mattias Ulbrich and 301 | Benjamin Wei{\ss}}, 302 | title = {The 1st {V}erified {S}oftware {C}ompetition: Experience Report}, 303 | booktitle = {Proceedings, 17th International Symposium on Formal Methods (FM 2011)}, 304 | editor = {Michael Butler and Wolfram Schulte}, 305 | volume = {6664}, 306 | series = {LNCS}, 307 | publisher = {Springer}, 308 | year = {2011}, 309 | } 310 | 311 | @inproceedings{fil:pas:stu:12, 312 | title = {{The 2nd Verified Software Competition: Experience Report}}, 313 | author = {Filli{\^a}tre, Jean-Christophe and Paskevich, Andrei and Stump, Aaron}, 314 | booktitle = {{COMPARE 2012, Comparative Empirical Evaluation of Reasoning Systems, 1st Intl. Workshop}}, 315 | address = {Manchester, United Kingdom}, 316 | editor = {Vladimir Klebanov and Bernhard Beckert and Armin Biere and Geoff Sutcliffe}, 317 | series = {CEUR Workshop Proceedings}, 318 | volume = {873}, 319 | pages = {36-49}, 320 | year = {2012}, 321 | month = Jun, 322 | } 323 | -------------------------------------------------------------------------------- /doc/cbench.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{listings} 3 | \usepackage[hidelinks]{hyperref} 4 | \usepackage{color,rotating,graphicx} 5 | \usepackage[a4paper]{geometry} 6 | 7 | \newcount\linecount 8 | \newread\inputlines 9 | \def\wc#1{ 10 | \linecount=0 11 | \openin\inputlines=#1 12 | \ifeof\inputlines\else 13 | \catcode`\{=12\catcode`\}=12\readlines\catcode`\{=1\catcode`\}=2\fi 14 | } 15 | \def\readlines{ 16 | \read\inputlines to\inputline 17 | \ifeof\inputlines\closein\inputlines 18 | \else\advance\linecount by 1\readlines\fi 19 | } 20 | 21 | \lstset{ 22 | language=C, 23 | keepspaces=true, 24 | basicstyle=\ttfamily\small, 25 | keywordstyle=\color{darkblue}, 26 | emphstyle=\color{red}, 27 | numbers=left, 28 | numberstyle=\color{darkgray}\sffamily\mytiny, 29 | stepnumber=5, 30 | firstnumber=1, 31 | numberfirstline=true, 32 | showlines=true, 33 | numbersep=1.8em, 34 | tabsize=8, 35 | xleftmargin=1em, 36 | frame=single, 37 | %framerule=0pt, 38 | rulecolor=\color{lightgray}, 39 | framesep=5pt, 40 | stringstyle=\color{darkgray}, 41 | showstringspaces=false, 42 | morekeywords={size_t,uint16_t,uint32_t,uint64_t,mpz_t}, 43 | caption=\mylstname, 44 | captionpos=b, 45 | columns=fullflexible 46 | } 47 | \def\myunderline#1{{\color{gray}{\underline{\color{black}{#1}}}}} 48 | \def\mytiny#1{\raise.5pt\hbox{\tiny #1}} 49 | 50 | \makeatletter 51 | 52 | \def\reducevspace{} 53 | \lst@AddToHook{OnEmptyLine}{\vspace{-.2em}\def\reducevspace{\vspace{-.2em}}} 54 | \lst@AddToHook{EveryPar}{\reducevspace\def\reducevspace{}} 55 | 56 | \let\reallst@SkipOrPrintLabel=\lst@SkipOrPrintLabel 57 | \gdef\lst@numberfirstlinetrue{\let\lst@ifnumberfirstline\iftrue} 58 | \def\lst@SkipOrPrintLabel{\ifnum\c@lstnumber=\lst@lastline\lst@numberfirstlinetrue\fi 59 | \reallst@SkipOrPrintLabel} 60 | 61 | \lst@AddToHookAtTop{Init}{\def\lst@firstnumber{\lst@firstline}} 62 | \newcount\mylst@lastline 63 | \lst@AddToHook{Init}{\mylst@lastline=\lst@lastline\ifnum\mylst@lastline=9999999\wc{\lstname}\def\lst@lastline{\linecount}\fi} 64 | 65 | \DeclareRobustCommand{\mylstname}{% 66 | \begingroup 67 | \def\textendash{-}% 68 | \filename@parse{\lstname}% 69 | \texttt{\filename@base.\filename@ext}% 70 | \endgroup 71 | } 72 | 73 | \makeatother 74 | 75 | \renewcommand{\lstlistingname}{Program} 76 | \definecolor{darkgray}{RGB}{102,102,102} 77 | \definecolor{gray}{RGB}{153,153,153} 78 | \definecolor{lightgray}{RGB}{204,204,204} 79 | \definecolor{darkblue}{RGB}{0,0,153} 80 | 81 | \def\toolong{$\hspace{-100cm}$} 82 | 83 | \begin{document} 84 | 85 | \title{A benchmark for C program verification} 86 | \author{% 87 | Marko van Eekelen \and 88 | Daniil Frumin \and 89 | Herman Geuvers \and 90 | L\'eon Gondelman \and 91 | Robbert Krebbers \and 92 | Marc Schoolderman \and 93 | Sjaak Smetsers \and 94 | Freek Verbeek \and 95 | Beno\^it Viguier \and 96 | Freek Wiedijk 97 | } 98 | %\institute{ 99 | %Institute for Computing and Information Sciences \\ 100 | %Radboud University Nijmegen \\ 101 | %Toernooiveld 212, 6525 EC Nijmegen, The Netherlands 102 | %} 103 | \date{April 1, 2019} 104 | \maketitle 105 | 106 | \begin{abstract} 107 | \noindent 108 | We present twenty-five C programs, as a benchmark for 109 | C program verification using formal methods. 110 | % 111 | This benchmark can be used for system demonstration, 112 | for comparison of verification effort between systems, 113 | and as a friendly competition. 114 | For this last purpose, we give a scoring formula that allows 115 | a verification system to score up to a hundred points. 116 | \end{abstract} 117 | 118 | \section{Introduction} 119 | 120 | Here is a challenge for people who are interested in practical C program verification using formal methods. 121 | Show us how to verify the correctness of the twenty-five programs in this paper. 122 | The paper and the sources of these programs can be found at: 123 | \begin{center} 124 | \begin{tabular}{l} 125 | \url{https://arxiv.org/abs/1904.01009} \\ 126 | \url{https://github.com/cverified/cbench/} \\ 127 | \url{https://www.cs.ru.nl/~freek/cbench/} 128 | \end{tabular} 129 | \end{center} 130 | \looseness=-1 131 | If you take this challenge, we will add 132 | your work (or a pointer to it, as you prefer) to the repository. 133 | 134 | In our Sovereign project \cite{eek:geu:sme:wie:14}, which has as its focus the safety and correctness of industrial programs, we \emph{are} interested in practical C program verification. 135 | Therefore we would like to have a clearer overview of frameworks for doing this. 136 | At first we planned to only have a few small programs for trying out the different systems (e.g., \cite{app:11}, \cite{cor:cuo:kir:mar:pre:puc:sig:yak:18}, \cite{dah:mos:san:tob:sch:09}, \cite{gre:and:klei:12}, \cite{jac:sma:phi:vog:pen:pie:11}). 137 | However, this then grew into this benchmark. 138 | 139 | The original idea of this benchmark was that it should be about five programs. 140 | It will be completely clear what these programs are when one sees the names: 141 | \begin{center} 142 | \begin{tabular}{ll} 143 | \lstinline|fac| & the basis \\ 144 | \lstinline|cat| & I/O \\ 145 | \lstinline|malloc| & linked datastructures, memory \\ 146 | \lstinline|qsort| & arrays, recursion, function pointers \\ 147 | \lstinline|sqrt| & floating point 148 | \end{tabular} 149 | \end{center} 150 | The few keywords given here indicate why we chose these five programs. 151 | (Obvious additions to this list are \texttt{fib} and \texttt{gcd}, but we consider these `more of the same' 152 | with respect to \texttt{fac}.) 153 | 154 | For each of these programs we now have several variants, ranging from very small with only a few lines of code to significant programs with reasonable behaviors. 155 | We intentionally kept the programs in this benchmark on the 156 | spectrum: 157 | \begin{center} 158 | \begin{picture}(200,35) 159 | \put(0,20){\line(1,0){200}} 160 | \put(0,17){\line(0,1){6}} 161 | \put(200,17){\line(0,1){6}} 162 | \put(0,10){\makebox(0,0){\emph{{\small simplest version}}}} 163 | \put(200,10){\makebox(0,0){\emph{{\small real life implementation}}}} 164 | \end{picture} 165 | \end{center} 166 | \noindent 167 | Altogether this gives twenty-five variations on those five programs. 168 | Three of these are not written by us, but are GNU implementations \cite{sta:02} that are actually used by many people. 169 | 170 | To turn this into a benchmark, then, we award four points for a proper verification of any of the programs. 171 | This means that it is possible to score: 172 | $$25 \times \mbox{$4$ points} = \mbox{$100$ points}$$ 173 | To get all four points for a program, one should both show that it does not exhibit undefined 174 | behavior and prove its functional correctness. 175 | Points will be subtracted for the following simplifications: 176 | \begin{center} 177 | \begin{tabular}{ll} 178 | no verification of defined behavior & $-1$ \\ 179 | no verification of functional correctness & $-1$ \\ 180 | verified modified code, still valid C & $-1$ \\ 181 | verified only a model of the code & $-2$ 182 | \end{tabular} 183 | \end{center} 184 | For example, if one only verifies functional correctness of a model 185 | of the program, one only gets $4 - 1 - 2 = 1$ point ($-1$ for not verifying well-definedness, 186 | and $-2$ for only verifying a model) instead of four. 187 | We include the option to modify the code a bit (with the loss of one point), 188 | because we expect some frameworks to have restrictions on the code they 189 | can verify. 190 | 191 | To phrase this more positively, another way to state the way points are awarded is: 192 | \begin{center} 193 | \begin{tabular}{ll} 194 | verification of defined behavior & $+1$ \\ 195 | verification of functional correctness & $+1$ \\ 196 | verified valid C & $+1$ \\ 197 | verified unmodified code & $+1$ 198 | \end{tabular} 199 | \end{center} 200 | For the last point it is allowed to add special comments to 201 | the code to enable the verification, like in the ACSL language \cite{bau:cuo:fil:mar:mon:moy:pre:16}. 202 | 203 | What it means to correctly verify defined behavior, whether a tool 204 | models C accurately (a subject that can lead to heated debate), and how much modification to the code is allowed 205 | for the program to still be `the same', we intentionally leave open. 206 | This is a friendly challenge, and should not be taken too seriously: 207 | if someone wants to award him- or herself a certain number of points 208 | for a verification effort, they should feel free to do so. 209 | We primarily hope this `benchmark' will be useful for demonstrating and comparing verification frameworks on actual C code. 210 | 211 | Exactly what it \emph{means} to `verify' code like this we also intentionally 212 | leave open. 213 | One is free to decide for oneselves what the specification for the programs should be. 214 | In practice, we expect that this means that one has to give: 215 | \begin{itemize} 216 | \item 217 | Restrictions on the C implementation. 218 | \item 219 | Pre-conditions for the code, e.g., restrictions on the input. 220 | \item 221 | Specification of the behavior of the code, e.g., appropriate post-conditions. 222 | \end{itemize} 223 | The C standard \cite{iso:11} has the notion of \emph{implementation-defined 224 | behavior}. 225 | This first item is about making 226 | explicit under what implementations the program should work. 227 | 228 | For example, the last programs in our benchmark presuppose IEEE 754-compliant 229 | floating point numbers. 230 | While the object representation of floating point numbers is \emph{not} im\-ple\-men\-ta\-tion-defined (but unspecified), 231 | there is the \lstinline|__STDC_IEC_559__| pre-defined constant, which \emph{is} implementation-defined. 232 | The restriction on the C implementation for these programs then might be that 233 | te implementation has to define that constant appropriately, 234 | in which case we can assume that the object representation for floating point numbers matches the IEEE 754 standard. 235 | Similarly, there might be restrictions on the integer sizes to be `large enough', or struct layouts to be appropriate to the program. 236 | 237 | \begin{samepage} 238 | Here then is a list of our twenty-five programs, with a table 239 | of the C features that each of these programs exercises: 240 | \begingroup 241 | \def\u#1{\emph{#1}} 242 | \def\v#1{\begin{sideways}\u{#1}\end{sideways}} 243 | \def\w#1{\hspace{-2pt}\v{#1}\hspace{2pt}} 244 | \def\x{$\times$} 245 | \begin{center} 246 | \medskip 247 | \tabcolsep=2pt 248 | \toolong\begin{tabular}{rclcrcccccccccccccccccccccccccc} 249 | \v{program number} && \v{filename} & \v{type} & \v{lines of code} &$\hspace{9pt}$& \w{function calls} & \w{standard library calls} & \w{other library calls} & \w{recursion} &$\hspace{3pt}$ & \w{preprocessor: includes} & \w{preprocessor: defines} &$\hspace{3pt}$ & \w{input/output} & \w{threads} &$\hspace{3pt}$& \w{exit} & \w{break/continue} & \w{switch} & \w{labels/goto} &$\hspace{3pt}$& \w{arrays/pointers} & \w{function pointers} & \w{structs} & \w{unions} & \w{defined types} & \w{typedefs} &$\hspace{3pt}$& \w{floating point} & \w{IEEE 754 floating point} 250 | \\ 251 | \noalign{\vspace{3pt}} 252 | 1 && \lstinline|fac1.c| & C & 3 &&&&&&&&&&&&&&&&&&&&&&&&&& \\ 253 | 2 && \lstinline|fac2.c| & C & 3 &&&&&&&&&&&&&&&&&&&&&&&&&& \\ 254 | 3 && \lstinline|fac3.c| & F & 9 &&&&&&&&&&&&&&&&&&&&&&&&&& \\ 255 | 4 && \lstinline|fac4.c| & F & 5 && \x &&& \x &&&&&&&&&&&&&&&&&&&&& \\ 256 | 5 && \lstinline|fac5.c| & S & 20 &&& \x & \x &&& \x &&& \x &&&&&&&&&&&& \x &&&& \\ 257 | 6 && \lstinline|fac6.c| & S & 70 && \x & \x && \x && \x & \x && \x &&& \x &&&&&&&&& \x &&&& \\ 258 | 7 && \lstinline|cat1.c| & C & 2 &&& \x &&&&&&& \x &&&&&&&&&&&&&&&& \\ 259 | 8 && \lstinline|cat2.c| & S & 13 &&& \x &&&& \x &&& \x &&&&&&&& \x &&&& \x &&&& \\ 260 | 9 && \lstinline|cat3.c| & S & 76 && \x & \x & \x &&& \x &&& \x &&& \x & \x &&&& \x &&&& \x &&&& \\ 261 | 10 && \href{https://github.com/coreutils/coreutils/blob/v8.27/src/cat.c}{\lstinline|coreutils/src/cat.c|} & R & ${\sim}800$ && \x & \x & \x &&& \x & \x && \x &&& \x && \x & \x && \x && \x && \x &&&& \\ 262 | 11 && \lstinline|malloc1.c| & F & 16 &&&&&&&& \x &&&&&&&&&& \x &&&&&&&& \\ 263 | 12 && \lstinline|malloc2.c| & F & 28 &&&&&&&& \x &&&&&&&&&& \x &&& \x &&&&& \\ 264 | 13 && \lstinline|malloc3.c| & F & 26 &&&&&&&& \x &&&&&&&&&& \x &&& \x &&&&& \\ 265 | 14 && \lstinline|malloc4.c| & F & 180 && \x &&&&& \x & \x &&&&&&&&&& \x & \x & \x && \x & \x &&& \\ 266 | 15 && \href{https://github.com/bminor/glibc/blob/glibc-2.24.90/malloc/malloc.c}{\lstinline|glibc/malloc/malloc.c|} & R & $\hspace{4pt}{\sim}6000$ && \x & \x & \x &&& \x & \x && \x & \x &&&& \x & \x && \x & \x & \x &&&&&& \\ 267 | 16 && \lstinline|qsort1.c| & F & 23 && \x &&& \x &&&&&&&&&&&&& \x &&&&&&&& \\ 268 | 17 && \lstinline|qsort2.c| & F & 50 && \x &&& \x &&&&&&&&&&& \x && \x &&&&&&&& \\ 269 | 18 && \lstinline|qsort3.c| & F & 50 && \x &&& \x &&& \x &&&&&& \x &&&& \x &&&&&&&& \\ 270 | 19 && \lstinline|qsort4.c| & F & 30 && \x &&& \x && \x & \x &&&&&& \x &&&& \x & \x &&&&&&& \\ 271 | 20 && \lstinline|qsort5.c| & S & 83 && \x & \x & \x & \x && \x & \x && \x & \x &&& \x &&&& \x &&&& \x &&&& \\ 272 | 21 && \lstinline|sqrt1.c| & F & 14 &&&&&&&&&&&&&&&&&&&&&&&&& \x & \\ 273 | 22 && \lstinline|sqrt2.c| & F & 12 &&&&&&&& \x &&&&&&&&&& \x &&&&&&& \x & \x \\ 274 | 23 && \lstinline|sqrt3.c| & F & 9 &&&&&&&&&&&&&&&&&&&&& \x &&&& \x & \x \\ 275 | 24 && \lstinline|sqrt4.c| & F & 190 && \x && \x &&&& \x &&&&&& \x & \x &&&&& \x & \x & \x & \x && \x & \x \\ 276 | 25 && \href{https://github.com/bminor/glibc/blob/glibc-2.24.90/soft-fp/sqrtsf2.c}{\lstinline|glibc/soft-fp/sqrtsf2.c|}$\hspace{8pt}$ & R & ${\sim}500$ && \x && \x &&& \x & \x &&&&&& \x & \x &&&&& \x & \x & \x & \x && \x & \x \\ 277 | \end{tabular}\toolong 278 | \medskip 279 | \end{center} 280 | \endgroup 281 | \end{samepage} 282 | \noindent 283 | There are different types of granularity in this list, ranging from only a fragment of a few isolated lines of code 284 | (in which case for example a Hoare triple for that fragment might be proved) to a full multi-file development that spans multiple directories. 285 | The four types are indicated with the following letters: 286 | \begin{center} 287 | \begin{tabular}{ll} 288 | C & code fragment \\ 289 | F & one or more functions \\ 290 | S & single source file \\ 291 | R & real life code, multiple source files 292 | \end{tabular} 293 | \end{center} 294 | The numbers of lines for the GNU programs are only rough indications. 295 | There are \emph{many} files (including many header files) involved in these 296 | programs, and we did not establish exactly which files are needed for 297 | these programs. 298 | (In the list we only list the primary source file, but the verification should 299 | include all other relevant source files.) 300 | Also, the exact line counts will be dependent on the version of the 301 | software. 302 | We do not want to restrict the version that should be used for this 303 | challenge, but while developing this benchmark we looked at version 304 | 8.27 of \texttt{coreutils}, and version 2.24.90 of \texttt{glibc}: 305 | \begin{center} 306 | \begin{tabular}{l} 307 | \url{https://github.com/coreutils/coreutils/tree/v8.27} \\ 308 | \url{https://github.com/bminor/glibc/tree/glibc-2.24.90} 309 | \end{tabular} 310 | \end{center} 311 | The listings in this paper only show the relevant parts of the programs. 312 | These are the parts that should be verified. 313 | However, in case it is useful to take other parts of these programs into 314 | account, that is of course allowed. 315 | Each of these programs (apart from two of the three GNU ones) is a program that can be compiled on its own, 316 | so each program has a \texttt{main} function in its file too. 317 | 318 | \section{Factorial}\label{fac} 319 | 320 | \subsection{A simple for loop} 321 | The very first program fragment is a \texttt{for} loop, 322 | multiplying the numbers from 1 to \texttt{n}: 323 | \lstinputlisting[linerange={6-8}]{../src/fac/fac1.c} 324 | This program has a straight-forward counterpart in most 325 | programming languages, so it should be easy to model it in any 326 | system. 327 | The declarations of \texttt{f}, \texttt{i} and \texttt{n} are not part of this 328 | fragment, but of course should be taken into account when verifying this. 329 | 330 | In practice, this program will exhibit integer overflow when \texttt{n} is too large. 331 | With 32-bit integers this happens for $\texttt{n}\ge 13$. 332 | The exact way this is specified in the pre-condition is left open. 333 | For example both $\mbox{\lstinline{n}} < 13$ and $\mbox{\lstinline{n}}! \le \mbox{\lstinline{INT_MAX}}$ 334 | might be reasonable choices for this. 335 | 336 | \subsection{Turing's program} 337 | The second program fragment is very similar to the previous one, but is a bit more involved. 338 | This is a C rendering of a program by Alan Turing from his 1949 paper \cite{tur:49} 339 | on program verification: 340 | \lstinputlisting[linerange={6-8}]{../src/fac/fac2.c} 341 | This calculates factorial without using multiplication. 342 | The original version of this program was written for the Manchester Mark 1 computer \cite{wie:16}, but as far as we know no C compiler for that computer exists. 343 | 344 | \subsection{A function} 345 | We now wrap the code in a function. 346 | This time the verification has to be about pre- and post-conditions 347 | of C functions, not of isolated statements: 348 | \lstinputlisting[linerange={1-9},emph={fac,main}]{../src/fac/fac3.c} 349 | We used more `C-like' idiom in this example. 350 | For example, the update of the counter and the multiplication now 351 | happen together in a single statement, making this example slightly less trivial. 352 | 353 | \subsection{Recursion} 354 | We claimed that the for loop has a counterpart in most programming languages, 355 | but this might not hold for functional languages. 356 | Here is the obvious recursive definition of the factorial function in C: 357 | \lstinputlisting[linerange={1-5},emph={fac,main}]{../src/fac/fac4.c} 358 | When called with too large an \texttt{n} 359 | this program can overflow its stack 360 | (for example when compiled with \texttt{gcc} \texttt{-O0} and called with 361 | \texttt{1000000} this happens). 362 | %(although we did not succeed in having GCC compile this to a program with this behavior) 363 | The C standard does not address that issue, but the verification of this 364 | code might take this into account in its pre-condition. 365 | 366 | \subsection{Big numbers} 367 | Until now the output of the code is meaningless for most inputs because of overflow. 368 | The program might as well just index in a small array to get the appropriate 369 | output. 370 | Here is a version of the program that uses the GMP library \cite{gra:16} to 371 | compute factorial for larger inputs: 372 | \lstinputlisting[emph={main}]{../src/fac/fac5.c} 373 | A specification of this program should also contain appropriate specifications 374 | for the GMP types and functions being used here. 375 | This program computes the factorial of one million (a number of 5,565,709 decimal digits) 376 | in a few minutes. 377 | 378 | \subsection{Big numbers without a library} 379 | Here is a simple implementation of factorial with big number arithmetic without 380 | using an external library: 381 | \lstinputlisting[emph={calc_fac,print_digits,main}]{../src/fac/fac6.c} 382 | The output of the digits does not use \texttt{printf}, but prints 383 | the digits individually using \texttt{putchar}. 384 | However, for the error handling \texttt{fprintf} is used. 385 | 386 | This program is about ten times slower than the GMP version. 387 | 388 | \section{Cat} 389 | 390 | \subsection{The simplest input/output program} 391 | Input/output is underrated in C verification. 392 | For example, in the CH$_2$O semantics from Robbert Krebbers' very thorough PhD thesis \cite{kre:15} this 393 | is not properly modelled. 394 | However, we think that input/output (the way that 395 | software interacts with its environment) is a fundamental property of a program 396 | and should be treated as such. 397 | 398 | The simplest program with both input and output just copies its input to its output. 399 | In Unix this program is called \texttt{cat}, and the simplest C implementation of this behavior is: 400 | \lstinputlisting[linerange={8-9}]{../src/cat/cat1.c} 401 | How the functional behavior of this program should be {specified} is not addressed in this paper. 402 | 403 | \subsection{Buffering} 404 | In practice the previous program is slow, even though \texttt{getchar} internally uses a buffer. 405 | By putting an explicit buffer in the program, it gets as fast as the GNU implementation of \texttt{cat}: 406 | \lstinputlisting[emph={main}]{../src/cat/cat2.c} 407 | This program uses the \lstinline|size_t| type, because that is what the \lstinline|fread| function returns and the \lstinline|fwrite| function expects. 408 | Therefore the verification framework should know about this type, in order to be able to verify this example. 409 | 410 | This code is similar to the example program from \cite{gun:myr:kum:nor:17}. 411 | 412 | \subsection{A simplified version of the real program} 413 | Here is a simplified version of the GNU implementation of \texttt{cat}. 414 | The main missing functionality is that there are no command line options (`flags'). 415 | Also, we simplified the code quite a bit: 416 | \lstinputlisting[emph={error,main}]{../src/cat/cat3.c} 417 | This code does not use the standard C library functions 418 | \texttt{fread} and \texttt{fwrite}, but instead 419 | uses the basic Unix system calls \texttt{read} and \texttt{write}. 420 | Therefore, the code includes the \texttt{unistd.h} header file, 421 | and should be verified with a respect to a specification of a Unix 422 | environment. 423 | 424 | \subsection{The GNU version} 425 | This is the real program that the previous program was a simplified version of. 426 | When on a Linux system one runs \texttt{cat}, this is the code that is 427 | executed. 428 | 429 | The file \texttt{coreutils-8.27/src/cat.c} contains 768 lines of code, 430 | but that code includes eight GNU header files, 431 | links to a function for handling command line options, and uses 432 | the GNU function \texttt{xmalloc}, a wrapper around the C standard library function 433 | \texttt{malloc} which is defined in a different file. 434 | \addtocounter{lstlisting}{1} 435 | 436 | \section{Allocate memory} 437 | \subsection{The simplest allocator} 438 | Here is the simplest memory allocator for C possible. 439 | It just cuts off pieces of memory and does not support \texttt{free}: 440 | \lstinputlisting[linerange={1-16},emph={malloc}]{../src/malloc/malloc1.c} 441 | This code does not satisfy the alignment restrictions on the real 442 | C \texttt{malloc}. 443 | All that is guaranteed is that a block with the appropriate number of bytes is 444 | returned. 445 | 446 | This code is very similar to the memory allocator verified in \cite{ben:06,ben:06:1}. 447 | 448 | \subsection{A typed allocator} 449 | If one does not need arrays, a memory allocator for C is simple to write. 450 | Here is an allocator that allocates objects of a given type \texttt{T}. 451 | (The definition of this type is intentionally not given in the code 452 | fragment shown, as it should be irrelevant for the verification.) 453 | 454 | The code both has an array (to allocate from) and a linked list (for keeping 455 | track of the freed objects), which makes it a nice target for separation logic: 456 | \lstinputlisting[linerange={6-33},emph={T_alloc,T_free}]{../src/malloc/malloc2.c} 457 | 458 | \subsection{A typed allocator that does not need pointer casts} 459 | The previous program needs to get a pointer to a \texttt{union} \texttt{cell} 460 | from a pointer to the allocated \texttt{T} object that is in that cell. 461 | According to the C standard \cite{iso:11} this is allowed, as it says in 6.7.2.1/15: 462 | \begin{quote} 463 | [\,\dots] 464 | A pointer to a union object, suitably converted, 465 | points to each of its members (or if a member is a 466 | bit-field, then to the unit in which it resides), and 467 | vice versa. 468 | [\,\dots] 469 | \end{quote} 470 | However, in some formal versions of the C semantics \cite{kre:16} this is not allowed. 471 | Therefore, here is a variant of this code where the user needs to keep 472 | track of the \texttt{union} \texttt{cell} for him- or herself, 473 | and that problem is not present: 474 | \lstinputlisting[linerange={6-31},emph={T_alloc,T_free}]{../src/malloc/malloc3.c} 475 | 476 | \subsection{A simplified version of the real program} 477 | Here is a very much simplified version of the GNU implementation of \texttt{malloc} and \texttt{free} in \texttt{glibc}: 478 | \lstinputlisting[linerange={7-186},emph={malloc_init_state,free_unsorted_chunk,malloc,free,main}]{../src/malloc/malloc4.c} 479 | Some features of the real GNU malloc that are missing from this version: 480 | \begin{itemize} 481 | \item no fastbins 482 | \item just a single regular bin 483 | \item no bitmap to quickly find non-empty bins (not needed, as there is just one bin) 484 | \item no \texttt{sbrk} to get more memory (just one static array) 485 | \item memory never returned to the system (the \lstinline|av_top| pointer never decreases) 486 | \item no memory mapped blocks 487 | \item no thread-awareness 488 | \end{itemize} 489 | However, the free list in the one bin is still kept in sorted order, and still uses 490 | the \lstinline|fd_nextsize| and \lstinline|bk_nextsize| pointers to search 491 | for an appropriate block. 492 | 493 | \subsection{The GNU version} 494 | And again, the last program of this section is the full GNU implementation of \texttt{malloc} and \texttt{free} in \texttt{glibc}. 495 | The main file \lstinline|glibc/malloc/malloc.c| in version 2.24.90 of \texttt{glibc} has 5,289 lines of code, but this file depends on many other files. 496 | 497 | The file contains the sentence: 498 | \begin{quote} 499 | The implementation is in straight, hand-tuned ANSI C. 500 | \end{quote} 501 | Exactly what it means to say that this code is `ANSI C', and whether this is actually true, is an interesting question. 502 | \addtocounter{lstlisting}{1} 503 | 504 | \section{Quicksort} 505 | \subsection{Straight-forward quicksort}\label{qsort1} 506 | Here is a very straight-forward version of a quicksort function for 507 | an array of doubles: 508 | \lstinputlisting[linerange={4-26},emph={swap,quicksort,main}]{../src/qsort/qsort1.c} 509 | This function of course has to be called with \lstinline|quicksort(0, N - 1)|. 510 | 511 | We tried to make this code as simple as possible. 512 | For example it contains no \lstinline|return| or \lstinline|break| and only has a single swap. 513 | 514 | There is a variant of this in which there only is a single comparison between 515 | \lstinline|i| and \lstinline|j| (with the bounds in the recursive 516 | call different), but that really makes use of the fact 517 | that we used \lstinline|a[n]| for the pivot. 518 | For that reason we decided not to take that variant here, even though 519 | it is still shorter. 520 | The version here also works with different choices for the pivot, 521 | like taking the median or mean of some elements in the array. 522 | 523 | This program has the property that if the array is already sorted, then it needs stack space for the recursion proportional to the length of the array. 524 | On a Linux system with a (default) \texttt{stacksize} of 8MB, the full program, which 525 | has \texttt{N} equal to 666,666, fails after about three minutes with the error: 526 | \begin{quote} 527 | \lstinline|segmentation fault| 528 | %\lstinline|zsh: segmentation fault ./qsort1} \\ 529 | %\lstinline|./qsort1 416.58s user 0.52s system 61% cpu 11:16.09 total| 530 | \end{quote} 531 | It would be nice if the verification of this program would be compatible with this behavior, i.e., that it would not be possible to prove this program to be correct for too large \texttt{N}. 532 | 533 | \subsection{Hoare's version of quicksort} 534 | Here is a variation on the previous program. 535 | This is a C rendering of the programs in the original publication on 536 | quicksort by Tony Hoare 537 | \cite{hoa:61}: 538 | \lstinputlisting[linerange={17-66},emph={exchange,random,partition,quicksort,main}]{../src/qsort/qsort2.c} 539 | This program uses \lstinline{goto} instead of \lstinline{break}. 540 | The original Algol 60 version of this code uses the call-by-name feature of Algol 60 (which is 541 | more like macro expansion), 542 | which is modeled here by giving the \lstinline{partition} function pointers 543 | to the variables to be modified. 544 | 545 | \subsection{The algorithm in the real program} 546 | If we take the GNU implementation of quicksort, and simplify it and also make it 547 | only apply to arrays of doubles, this is what one gets: 548 | \lstinputlisting[linerange={1-50},emph={SWAP,quicksort,main}]{../src/qsort/qsort3.c} 549 | This is just a variation on the previous programs, but it has 550 | a few nice features, like using a macro for swapping elements in the array. 551 | One probably wants to prove this \emph{macro} correct, 552 | which means that just verifying the macro-expanded version of the 553 | program will not be too attractive in this case. 554 | 555 | Apart from the fact that this function only sorts doubles instead 556 | of sorting arrays with elements of an arbitrary type, 557 | it omits two optimizations from the GNU version of this code. 558 | This uses insertion sort when the size of the subarray drops 559 | below a certain threshold, 560 | and it manages a (short) \emph{explicit} stack for the recursive calls, 561 | instead of using the recursion of C. 562 | 563 | \subsection{Quicksort on arbitrary types} 564 | Here is a version of the simple version of quicksort that 565 | we gave in \ref{qsort1}, but this time for arbitrary types, so this is an 566 | implementation of the interface of the \lstinline{qsort} function in the C standard library: 567 | \lstinputlisting[linerange={1-30},emph={swap,qsort,main}]{../src/qsort/qsort4.c} 568 | Notable features of this program are function pointers, 569 | \lstinline|(void *)| pointers, and the use of \lstinline|memcpy| to 570 | copy C objects. 571 | 572 | \subsection{Parallel quicksort} 573 | Finally, here is a version of quicksort that uses threads. 574 | The basic idea of this program is that at most \lstinline|THREADS| threads will be 575 | running. 576 | Once a recursive call gets a piece of the array of which the size is 577 | below \lstinline|THRESHOLD| (which 578 | means the data will fit in the cache of one of the cores), a separate 579 | thread will be used for this if one is available. 580 | The count of free threads is kept in the variable \lstinline|available| 581 | for which a mutex is used when updating it. 582 | 583 | We did not use C11 threads for this, because we did not have a good implementation of it available. 584 | Instead this uses the pthreads library. 585 | The means the program might need to be compiled 586 | with \lstinline{-lpthread}. 587 | 588 | Again, algorithmically this is just the simple algorithm from \ref{qsort1}: 589 | \lstinputlisting[emph={run_quicksort,quicksort,main}]{../src/qsort/qsort5.c} 590 | 591 | \section{Square root} 592 | \subsection{Newton's approximation} 593 | The last class of examples in this benchmark are implementations 594 | of the square root function on single precision floating point numbers. 595 | Here is a simple version of an implementation that uses the Newton method: 596 | \lstinputlisting[linerange={1-14},emph={sqrt_newton,main}]{../src/sqrt/sqrt1.c} 597 | This will not always give exactly the right answer according to the IEEE 754 598 | standard, but it will be close. 599 | If a \lstinline|float| has finitely many different representations 600 | (which one might expect the C standard would enforce, because there are only 601 | finitely many different object representations), then this program will 602 | always terminate. 603 | 604 | It is interesting exactly what is provable about this program 605 | in a C implementation where one does not know how the floating 606 | point implementation works in detail. 607 | Maybe if there are some guarantees about relative error bounds 608 | of the arithmetic operations, an error bound on the result of this 609 | function can be proved. 610 | 611 | \subsection{An approximation of square root by bit shifting}\label{bitshift} 612 | The IEEE 754 representation of floating point numbers allows 613 | for an approximation to the square root function 614 | that can be calculated extremely fast. 615 | The counterpart for the inverse square root function (both square 616 | root and inverse square root 617 | use exactly the same trick) is known 618 | as `the \lstinline|0x5f3759df| method', 619 | after the magic constant that appears in it. 620 | (Comments in the first program that had this constant 621 | in it were \emph{evil floating point bit level hacking} and \emph{what the fuck?}) 622 | 623 | The implementation just consists of considering the bits of the number by casting it to an integer, 624 | shifting those bits one place to the right, and then adding a magic constant to that integer representation: 625 | \lstinputlisting[linerange={1-12},emph={sqrt_approx,main}]{../src/sqrt/sqrt2.c} 626 | It is surprising that this gives a sensible result. 627 | One is shifting one of the bits of the exponent into a bit of the 628 | mantissa, how is that going to make sense? 629 | However, when analyzing it more closely \cite{bli:97}, it turns 630 | out that this \emph{does} make sense, and that for sufficiently large inputs, it gives a continuous piecewise linear function that 631 | approximates the square root function quite well (it is exact 632 | on powers of four, see the graph in Fig.~\ref{sqrt_approx}.) 633 | The maximum error occurs when the argument is twice a power of four, and the 634 | relative error on those values is $(1\frac{1}{2} - \sqrt{2})/\sqrt{2} = \frac{3}{4}\sqrt{2} - 1 \approx 6.0660\% \approx 2^{-4.0431}$, 635 | which means that generally the first three bits of the fractional part will be correct. 636 | \begin{figure} 637 | \begin{center} 638 | \includegraphics[width=.9\textwidth]{sqrt_approx} 639 | \end{center} 640 | \caption{The graph of \lstinline|sqrt_approx|.}\label{sqrt_approx} 641 | \end{figure} 642 | 643 | Unlike the code in the next section, this function also makes sense if \lstinline|float|s 644 | do not have 32 bits single precision. 645 | All that is needed is that the bits are laid out in the style of a 646 | IEEE 754 representation. 647 | As was noted before, this can be established by the implementation-defined 648 | property of \lstinline|__STDC_IEC_559__| having an appropriate definition. 649 | 650 | We had some discussion whether to include this program in our benchmark. 651 | We wanted our examples to be `realistic', and this seems more of 652 | a cute hack than something resembling realistic code. 653 | Also, nowadays square root is supported by hardware, and getting a good approximation 654 | as a start for Newton's method is not really important anymore. 655 | However, this program is about the bit representation of floating point 656 | numbers, and about using casts to reinterpret one type as another (which is 657 | a common thing in C). 658 | For this reason we decided to still include this 659 | as one of our examples. 660 | 661 | \subsection{An approximation of square root by bit shifting that does not violate effective types}\label{sqrt3} 662 | The previous program uses type casts to get at the bits of a floating point number, 663 | in order to be able to shift them. 664 | However, that violates the \emph{effective type} rules, as described 665 | in 6.5/7 of the C11 standard. 666 | In fact, when compiled using GCC with the \lstinline|-Wall| and \lstinline|-O3| flags, 667 | the compiler emits the warning: 668 | \begin{quote} 669 | \lstinline[language=]|warning: dereferencing type-punned pointer will break strict-|\\ 670 | \lstinline[language=]|aliasing rules [-Wstrict-aliasing]| 671 | \end{quote} 672 | We now give a version of the same program that uses a \lstinline|union| to 673 | get at the bits of the \lstinline|float|, which means it 674 | does not suffer from this problem: 675 | \lstinputlisting[linerange={1-9},emph={sqrt_approx,main}]{../src/sqrt/sqrt3.c} 676 | Using a \lstinline|union| to get at the bits of an object is allowed by the C11 standard, as in 677 | footnote 95 of 6.5.2.3/3 it reads: 678 | \begin{quote} 679 | If the member used to read the contents of a union object is not the same as the member last used to 680 | store a value in the object, the appropriate part of the object representation of the value is reinterpreted 681 | as an object representation in the new type as described in 6.2.6 (a process sometimes called ``type 682 | punning''). This might be a trap representation. 683 | \end{quote} 684 | When using \lstinline|union|s, it is harder to write the constant to be 685 | added to the expression in a way that it will work whatever 686 | the number of bits in the floating point representation, and 687 | in such a way that the compiler will insert it as a constant in the code 688 | at compile time. 689 | To keep the program small, we therefore expanded this constant to its value for 32-bit 690 | floating point numbers: \lstinline|0x1fc00000|. %, or the decimal number 532,676,608. 691 | This means that to work correctly, this program needs an implementation with 32-bit IEEE 754 \lstinline|float|s. 692 | 693 | \subsection{A simplified version of a serious implementation} 694 | The GNU library \texttt{glibc} contains software implementations of 695 | the IEEE 754 operations in the subdirectory \texttt{soft-fp}. 696 | In the case of square root, the algorithm used is the square root 697 | analog of long division. 698 | The GNU code for this consists of a whole stack of macro definitions. 699 | When expanding all these definitions, and simplifying everything quite a bit, one gets: 700 | \lstinputlisting[linerange={1-190},emph={__sqrtsf2,main}]{../src/sqrt/sqrt4.c} 701 | This code implements IEEE 754 behavior, but (as the primary simplification) 702 | only implements the default rounding mode. 703 | The full GNU version supports the other rounding modes as well. 704 | Also, the full version implements more possible variant behaviors on not-a-numbers. 705 | 706 | Most of this code is about getting at the bits at the start and reassembling the 707 | floating point number at the end, and about 708 | handling various special cases like infinities, not-a-numbers, and 709 | denormalized numbers. 710 | The actual algorithm for the `long division' analog 711 | is in lines 103--125. 712 | 713 | \subsection{The GNU version} 714 | And the last program in our verification benchmark is the actual implementation 715 | of square root in \texttt{libc/soft-fp}. 716 | That code is a bit obfuscated, because many of the macros implement the operations 717 | for different floating point sizes at the same time. 718 | The function that should be verified is \lstinline|__sqrtsf2|, 719 | implemented in the file \lstinline|sqrtsf2.c|: 720 | \lstinputlisting[linerange={31-49},emph={__sqrtsf2}]{../src/sqrt/sqrtsf2.c} 721 | Of course the macros defined through the \lstinline|#include| lines pull in lots of other code from other files, and expand this program significantly. 722 | 723 | In the latest versions of \texttt{glibc} the source code of square root in \texttt{libc/soft-sp} has been moved to a larger file that contains many arithmetical operations together. 724 | However, we prefer to have the 25th program in our benchmark be about a single small source file that we essentially can include in this paper. 725 | For this reason, this benchmark stays linked to version 2.24.90 of \texttt{glibc}. 726 | 727 | \section{Versions} 728 | 729 | The benchmark presented in this paper will go through various versions. 730 | We will use dates for versioning. 731 | The initial version is dated April 1, 2019, and might be 732 | referred to as the \emph{April fool's} version. 733 | 734 | Every time a problem with one of the programs in this 735 | benchmark is discovered, we will modify the program to remove the problem, and give 736 | the benchmark a new version date. 737 | In that case we will add a short description to this section of the problem, how it was discovered and how the program was changed to remove the problem. 738 | This means that this section will be some kind of high level changelog. 739 | 740 | Note that bad behavior outside the 741 | intended domain of behavior of a program does not count as a problem. 742 | For example, integer overflow in the earlier factorial programs in Section~\ref{fac} 743 | is not a problem. 744 | This should be handled by a precondition of the correctness statement of the code, and 745 | does not merit modification of the code in the benchmark. 746 | 747 | \section{Discussion} 748 | We can imagine different reactions to the collection of programs that we present here: 749 | \begin{itemize} 750 | \item 751 | These programs are too easy. 752 | 753 | \item 754 | These programs are too hard. 755 | 756 | \item 757 | These programs are not too easy or too hard, but not interesting. 758 | 759 | \end{itemize} 760 | \noindent 761 | In the first case we would like to see how to verify them. 762 | If they are easy, showing how to do that should not be much work, right? 763 | In the second case we would like to know how far the technology 764 | currently reaches. 765 | We intentionally provided a spectrum from very small fragments 766 | to larger pieces of code, so if you have the second reaction then just show us how to do the easier ones. 767 | 768 | However, in the third case we disagree. 769 | This is based on actual programs from the GNU project, 770 | and as such are representative of real C programming. 771 | Why is it not interesting to be able to verify what 772 | to us are characteristic C programs? 773 | 774 | It was tempting to also include programs in our benchmark that are cute and/or dazzling. 775 | (The square root approximation by bit shifting in Section~\ref{bitshift} was borderline in this respect.) 776 | For instance, consider two possible additions to the factorial 777 | section, 778 | the first being a surprising application of the preprocessor: 779 | \lstinputlisting{../src/fac/facx.c} 780 | \lstinputlisting[language=]{../src/fac/facy.c} 781 | (it turns out that the factorial is calculated here at compile time), 782 | and the second being a price winning submission to the international 783 | obfuscated C code contest 784 | (it implements a functional language and then does the recursion by 785 | evaluating Church's $Y$-combinator.) 786 | However, we do not consider these two programs representative of 787 | real life C programming, so we resisted the temptation to include them in our benchmark. 788 | 789 | There are twenty-five programs in this paper, and there are multiple 790 | frameworks for formal C verification out there, like the ones described 791 | in \cite{app:11}, \cite{cor:cuo:kir:mar:pre:puc:sig:yak:18}, \cite{dah:mos:san:tob:sch:09}, \cite{gre:and:klei:12} and \cite{jac:sma:phi:vog:pen:pie:11}. 792 | We think this could be a great source for student projects. 793 | Just say, for example: `prove the correctness of program number three in framework 794 | number one' (actually something close to that one already has been done, see the slides of \cite{wie:16:1}). 795 | That way we will get a good comparison of what are the strengths and 796 | weaknesses of the different current approaches for formal C verification. 797 | 798 | \section{Related work} 799 | 800 | Benchmarks/competitions very similar to the one presented in this paper 801 | already exist: 802 | \begin{itemize} 803 | \item 804 | VACID-0 \cite{lei:mos:10}: \\ 805 | \url{https://archive.codeplex.com/?p=vacid} 806 | 807 | \item 808 | Verified Software Competition \cite{fil:pas:stu:12,kle:mul:sha:lea:wus:alk:art:bro:cha:coh:hil:jac:lei:mon:pie:pol:rid:sma:tob:tue:ulb:wei:11}. %\\ 809 | %\url{https://sites.google.com/a/vscomp.org/main/} 810 | 811 | \item 812 | VerifyThis Competition: \\ 813 | \url{http://www.pm.inf.ethz.ch/research/verifythis.html} 814 | 815 | \end{itemize} 816 | The main difference from the benchmark 817 | presented here is that they do not target C explicitly. 818 | Yet, they sometimes use C code in their statements, and sometimes 819 | participants are using C for their solutions. 820 | 821 | There are also benchmarks that \emph{are} about specific programming languages, 822 | which often have a C section, like for example: 823 | \begin{itemize} 824 | \item 825 | Collection of Verification Tasks of the SoSy-Lab at the Ludwig-Maximilian University in Munich: \\ 826 | \url{https://github.com/sosy-lab/sv-benchmarks/tree/master/c} 827 | 828 | \end{itemize} 829 | However, in that case the focus is not so much on formally proving that programs 830 | are fully correct, but on benchmarking the performance of non-interactive tools for discovering problems in the programs. 831 | 832 | \section*{Acknowledgments} 833 | Thanks to Jean-Christophe Filli\^atre, Andrew Appel and Sandrine Blazy for many helpful comments. 834 | 835 | \bibliographystyle{plain} 836 | \bibliography{cbench} 837 | 838 | \end{document} 839 | -------------------------------------------------------------------------------- /doc/sqrt_approx.ps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%BoundingBox: 0 0 500 300 3 | 25 22 translate 4 | 94 dup scale 5 | .005 setlinewidth 6 | 0 0 moveto 0 2.8 lineto stroke 7 | 0 0 moveto 5 0 lineto stroke 8 | /x 0 def 9 | x x sqrt moveto 10 | 500 {/x x 0.01 add def x x sqrt lineto} repeat 11 | stroke 12 | gsave 13 | 1 0 0 setrgbcolor 14 | /x 4 def 15 | 5 2.25 moveto 16 | 10 {/y x sqrt def x y lineto x 2 div y .75 mul lineto /x x 4 div def} repeat 17 | stroke 18 | grestore 19 | gsave 20 | [.01 .01] 0 setdash 21 | 1 0 moveto 1 1 lineto stroke 22 | 0 1 moveto 1 1 lineto stroke 23 | 2 0 moveto 2 1.5 lineto stroke 24 | /y 2 sqrt def 25 | 0 y moveto 2 y lineto stroke 26 | 0 1.5 moveto 2 1.5 lineto stroke 27 | 4 0 moveto 4 2 lineto stroke 28 | 0 2 moveto 4 2 lineto stroke 29 | grestore 30 | /Helvetica findfont 0.12 scalefont setfont 31 | %0 (0) stringwidth pop 2 div sub -.15 moveto (0) show 32 | 1 (1) stringwidth pop 2 div sub -.15 moveto (1) show 33 | 2 (2) stringwidth pop 2 div sub -.15 moveto (2) show 34 | 4 (4) stringwidth pop 2 div sub -.15 moveto (4) show 35 | %-.05 (0) stringwidth pop sub -.03 moveto (0) show 36 | -.06 (1) stringwidth pop sub .97 moveto (1) show 37 | -.06 (1.5) stringwidth pop sub 1.47 moveto (1.5) show 38 | -.06 (2) stringwidth pop sub 1.97 moveto (2) show 39 | showpage 40 | -------------------------------------------------------------------------------- /src/cat/cat1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main() 5 | { 6 | int c; 7 | 8 | while ((c = getchar()) != EOF) 9 | putchar(c); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/cat/cat2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char buf[128*1024]; 4 | 5 | int 6 | main() 7 | { 8 | size_t count; 9 | 10 | while ((count = fread(buf, 1, sizeof(buf), stdin)) > 0) 11 | fwrite(buf, 1, count, stdout); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/cat/cat3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | char *program_name, *infile; 10 | int input_desc, ok = 1; 11 | 12 | void 13 | error(int status, int errnum, char *message) 14 | { 15 | fprintf(stderr, "%s: ", program_name); 16 | if (errnum) 17 | perror(message); 18 | else 19 | fprintf(stderr, "%s\n", message); 20 | fflush(stderr); 21 | if (status) 22 | exit(status); 23 | ok = 0; 24 | } 25 | 26 | int 27 | main(int argc, char **argv) 28 | { 29 | size_t insize = 128*1024, page_size = getpagesize(), count, n_rw; 30 | char *inbuf, *buf, *ptr; 31 | int argind = 0; 32 | 33 | program_name = argv[argind++]; 34 | infile = "-"; 35 | inbuf = malloc(insize + page_size - 1); 36 | if (!inbuf) 37 | error(EXIT_FAILURE, 0, "memory exhausted"); 38 | buf = inbuf + page_size - 1; 39 | buf = buf - (uintptr_t) buf % page_size; 40 | do { 41 | if (argind < argc) 42 | infile = argv[argind]; 43 | if (*infile == '-' && infile[1]) 44 | error(0, 0, "options not implemented"); 45 | input_desc = 46 | strcmp(infile, "-") == 0 ? STDIN_FILENO : open(infile, O_RDONLY); 47 | if (input_desc < 0) { 48 | error(0, 1, infile); 49 | continue; 50 | } 51 | while (1) { 52 | count = read(input_desc, buf, insize); 53 | if (count == (size_t) -1) { 54 | error(0, 1, infile); 55 | break; 56 | } 57 | if (count == 0) 58 | break; 59 | ptr = buf; 60 | while (count > 0) { 61 | n_rw = write(STDOUT_FILENO, ptr, count); 62 | if (n_rw == (size_t) -1) 63 | break; 64 | if (n_rw == 0) 65 | break; 66 | count -= n_rw; 67 | ptr += n_rw; 68 | } 69 | if (count != 0) 70 | error(EXIT_FAILURE, 1, "write error"); 71 | } 72 | if (strcmp(infile, "-") != 0 && close(input_desc) < 0) 73 | error(0, 1, infile); 74 | } while (++argind < argc); 75 | return ok ? EXIT_SUCCESS : EXIT_FAILURE; 76 | } 77 | -------------------------------------------------------------------------------- /src/fac/fac1.c: -------------------------------------------------------------------------------- 1 | int 2 | main() 3 | { 4 | int n = 5, i, f; 5 | 6 | f = 1; 7 | for (i = 1; i <= n; i++) 8 | f = f*i; 9 | return f; 10 | } 11 | -------------------------------------------------------------------------------- /src/fac/fac2.c: -------------------------------------------------------------------------------- 1 | int 2 | main() 3 | { 4 | int s, r, n = 5, u, v; 5 | 6 | for (u = r = 1; v = u, r < n; r++) 7 | for (s = 1; u += v, s++ < r; ) 8 | ; 9 | return u; 10 | } 11 | -------------------------------------------------------------------------------- /src/fac/fac3.c: -------------------------------------------------------------------------------- 1 | int 2 | fac(int n) 3 | { 4 | int f = 1; 5 | 6 | while (n) 7 | f *= n--; 8 | return f; 9 | } 10 | 11 | int 12 | main() 13 | { 14 | return fac(5); 15 | } 16 | -------------------------------------------------------------------------------- /src/fac/fac4.c: -------------------------------------------------------------------------------- 1 | int 2 | fac(int n) 3 | { 4 | return n == 0 ? 1 : n*fac(n - 1); 5 | } 6 | 7 | int 8 | main() 9 | { 10 | return fac(5); 11 | } 12 | -------------------------------------------------------------------------------- /src/fac/fac5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "gmp.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int n, i; 9 | mpz_t f; 10 | 11 | n = atoi(argv[1]); 12 | mpz_init(f); 13 | mpz_set_ui(f, 1); 14 | for (i = 1; i <= n ; i++) 15 | mpz_mul_ui(f, f, i); 16 | mpz_out_str(stdout, 10, f); 17 | putchar('\n'); 18 | mpz_clear(f); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /src/fac/fac6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define M 1000000000 6 | #define D 9 7 | 8 | int h = 0; 9 | 10 | int 11 | calc_fac(uint32_t *a, int L, uint64_t n) 12 | { 13 | uint64_t b, c; 14 | int i, l; 15 | 16 | a[0] = 1; 17 | for (i = 1; i < L; i++) 18 | a[i] = 0; 19 | l = 1; 20 | while (n) { 21 | c = 0; 22 | for (i = 0; i < l || c; i++) { 23 | b = n*a[i] + c; 24 | c = b/M; 25 | a[i] = b - c*M; 26 | } 27 | if (i > l) 28 | l = i; 29 | n--; 30 | } 31 | return l; 32 | } 33 | 34 | void 35 | print_digits(int n, int c) 36 | { 37 | int d; 38 | 39 | if (c <= 0) 40 | return; 41 | print_digits(n/10, c - 1); 42 | d = n%10; 43 | if (h || d) { 44 | putchar('0' + d); 45 | h = 1; 46 | } 47 | } 48 | 49 | int 50 | main(int argc, char **argv) 51 | { 52 | uint32_t *a; 53 | int n, m, L, i; 54 | 55 | if (argc != 2) { 56 | fprintf(stderr, "usage: %s input\n", *argv); 57 | exit(2); 58 | } 59 | n = atoi(argv[1]); 60 | if (n < 0) { 61 | fprintf(stderr, "%s: input is negative\n", *argv); 62 | exit(2); 63 | } 64 | L = 0; 65 | for (m = n; m; m = m/10) 66 | L++; 67 | L = L*n/D + 1; 68 | a = malloc(L*sizeof(*a)); 69 | if (!a) { 70 | fprintf(stderr, "%s: out of memory\n", *argv); 71 | exit(1); 72 | } 73 | L = calc_fac(a, L, n); 74 | for (i = L - 1; i >= 0; i--) { 75 | print_digits(a[i], D); 76 | } 77 | putchar('\n'); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/fac/facx.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* after all the macro violence, PRIM(fac) will be left in the output; 4 | one solution is to define these as ... existing nowhere */ 5 | 6 | extern int fac(); 7 | extern int (*PRIM())(); 8 | 9 | #define NOTHING 10 | #define PRIM(f) f##_prim 11 | 12 | /* NOTHING between PRIM and (f) prevens expansion of PRIM */ 13 | #define REC PRIM NOTHING 14 | 15 | /* this simply forces the re-scanning of x (for macros) many times */ 16 | #define EVAL1(x) x 17 | #define EVAL2(x) EVAL1(EVAL1(EVAL1(EVAL1(x)))) 18 | #define EVAL3(x) EVAL2(EVAL2(EVAL2(EVAL2(x)))) 19 | 20 | #define fac_prim(n) (n)<=0? 1 : (n)*(REC(fac)(n-1)) 21 | #define fac(n) EVAL3(PRIM(fac)(n)) 22 | 23 | int main() 24 | { 25 | printf("%ld\n", fac(20L)); 26 | } 27 | -------------------------------------------------------------------------------- /src/fac/facy.c: -------------------------------------------------------------------------------- 1 | #include/*Y=\f*/ 2 | #include/*.(\x.f(*/ 3 | #define z return/*xx))(\x.*/ 4 | #include/*f(xx))*/ 5 | typedef union w w;union w{ 6 | #define L(f,y,x,t) w _ ##\ 7 | f(w x,...){va_list argh;w\ 8 | y; va_start(argh,x);y= *\ 9 | (va_arg(argh,w*));va_end\ 10 | (argh);z(t);} w f (w fw)\ 11 | {r((w){.c= &_## f}, fw);} 12 | int _; void*p;w(*c)(w,... 13 | #define r(x,y)w*k=malloc\ 14 | (sizeof(w)<<1); k[0]= x\ 15 | ; k[1]=y; z((w) {.p= k}) 16 | #define l(f,x,t)w _##f(\ 17 | w x,...){z(t);}w f={.p\ 18 | =(w[1]){{.c= &_##f}}}; 19 | );};w a(w f,w x){w*d=f 20 | .p;z((*d->c)(x,d+1) 21 | 22 | 23 | ) ; } 24 | w a_(w f,w fw){r(f, 25 | fw);}w _(w f){w*k=f.p,r= 26 | a(*k,k[1]); free(k) ;z(r);} 27 | L(F,f,x,(w){._=x._?x._*a(_(f), 28 | (w){._=x._-1})._:1})l(F_,f,F(f) 29 | )L( W,(f),/*=\*/x,a(f,a_(x,x)) 30 | )l( Y,/*=\*/f,a(W(f),W(f)) 31 | )int main(){printf("%.""f\n", 32 | a(a(Y,F_),(w){._=10})._ 33 | /60./60/24/*d */ 34 | ) ; } 35 | -------------------------------------------------------------------------------- /src/malloc/malloc1.c: -------------------------------------------------------------------------------- 1 | #define HEAPSIZE 1000 2 | 3 | unsigned char heap[HEAPSIZE]; 4 | unsigned char *limit = heap; 5 | 6 | unsigned char * 7 | malloc(int n) 8 | { 9 | unsigned char *ptr; 10 | 11 | if (n <= 0 || n > heap + HEAPSIZE - limit) 12 | return 0; 13 | ptr = limit; 14 | limit += n; 15 | return ptr; 16 | } 17 | 18 | int 19 | main() 20 | { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/malloc/malloc2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { char contents[42]; } T; 4 | 5 | 6 | #define HEAPSIZE 1000 7 | 8 | union cell { T allocated; union cell *next_free; } heap[HEAPSIZE]; 9 | union cell *limit = heap, *first_free = 0; 10 | 11 | T * 12 | T_alloc() 13 | { 14 | union cell *ptr = first_free; 15 | 16 | if (ptr) 17 | first_free = first_free->next_free; 18 | else { 19 | if (limit >= heap + HEAPSIZE) 20 | return 0; 21 | ptr = limit++; 22 | } 23 | return &(ptr->allocated); 24 | } 25 | 26 | void 27 | T_free(T *T_ptr) 28 | { 29 | union cell *ptr = (union cell *) T_ptr; 30 | 31 | ptr->next_free = first_free; 32 | first_free = ptr; 33 | } 34 | 35 | 36 | void 37 | vstrcpy(char *dest, char *src) 38 | { 39 | while (*src) 40 | *dest++ = *src++; 41 | } 42 | 43 | int 44 | main() 45 | { 46 | T *p; 47 | p = T_alloc(); 48 | vstrcpy(p->contents, "foo"); 49 | printf("%s\n", p->contents); 50 | T_free(p); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/malloc/malloc3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { char contents[42]; } T; 4 | 5 | 6 | #define HEAPSIZE 1000 7 | 8 | union cell { T allocated; union cell *next_free; } heap[HEAPSIZE]; 9 | union cell *limit = heap, *first_free = 0; 10 | 11 | union cell * 12 | T_alloc() 13 | { 14 | union cell *ptr = first_free; 15 | 16 | if (ptr) 17 | first_free = first_free->next_free; 18 | else { 19 | if (limit >= heap + HEAPSIZE) 20 | return 0; 21 | ptr = limit++; 22 | } 23 | return ptr; 24 | } 25 | 26 | void 27 | T_free(union cell *ptr) 28 | { 29 | ptr->next_free = first_free; 30 | first_free = ptr; 31 | } 32 | 33 | 34 | void 35 | vstrcpy(char *dest, char *src) 36 | { 37 | while (*src) 38 | *dest++ = *src++; 39 | } 40 | 41 | int 42 | main() 43 | { 44 | union cell *p; 45 | p = T_alloc(); 46 | vstrcpy(p->allocated.contents, "foo"); 47 | printf("%s\n", p->allocated.contents); 48 | T_free(p); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/malloc/malloc4.c: -------------------------------------------------------------------------------- 1 | #if __STDC_VERSION__ < 201100 2 | typedef long double max_align_t; 3 | #define _Alignof(x) (__alignof__(x)) 4 | #endif 5 | 6 | 7 | #include 8 | 9 | #define HEAPSIZE 1000 10 | union { 11 | unsigned char bytes[HEAPSIZE]; 12 | max_align_t align; 13 | } heap; 14 | 15 | struct malloc_chunk { 16 | size_t mchunk_prev_size; 17 | size_t mchunk_size; 18 | struct malloc_chunk *fd; 19 | struct malloc_chunk *bk; 20 | struct malloc_chunk *fd_nextsize; 21 | struct malloc_chunk *bk_nextsize; 22 | }; 23 | 24 | typedef struct malloc_chunk *mchunkptr; 25 | typedef struct malloc_chunk *mbinptr; 26 | 27 | mchunkptr av_top; 28 | struct malloc_chunk av_bin; 29 | 30 | #define chunk2mem(p) ((void*) ((char*) (p) + 2*SIZE_SZ)) 31 | #define mem2chunk(mem) ((mchunkptr) ((char*) (mem) - 2*SIZE_SZ)) 32 | 33 | #define SIZE_SZ (sizeof(size_t)) 34 | #define MALLOC_ALIGNMENT (2*SIZE_SZ < _Alignof(max_align_t) \ 35 | ? _Alignof(max_align_t) : 2*SIZE_SZ) 36 | #define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) 37 | 38 | #define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk)) 39 | #define MINSIZE (unsigned long) \ 40 | (((MIN_CHUNK_SIZE + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) 41 | 42 | #define PREV_INUSE 0x1 43 | #define SIZE_BITS (PREV_INUSE) 44 | 45 | #define chunksize(p) (chunksize_nomask(p) & ~(SIZE_BITS)) 46 | #define prev_inuse(p) ((p)->mchunk_size & PREV_INUSE) 47 | #define chunksize_nomask(p) ((p)->mchunk_size) 48 | #define prev_size(p) ((p)->mchunk_prev_size) 49 | #define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s))) 50 | 51 | #define set_head(p, s) ((p)->mchunk_size = (s)) 52 | #define set_foot(p, s) \ 53 | (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s)) 54 | 55 | #define inuse_bit_at_offset(p, s) \ 56 | (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE) 57 | #define set_inuse_bit_at_offset(p, s) \ 58 | (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE) 59 | #define clear_inuse_bit_at_offset(p, s) \ 60 | (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~PREV_INUSE) 61 | 62 | #define unlink(P, BK, FD) \ 63 | { FD = P->fd; BK = P->bk; FD->bk = BK; BK->fd = FD; } 64 | 65 | static void 66 | free_unsorted_chunk(mchunkptr p, size_t size) 67 | { 68 | mchunkptr fwd, bck; 69 | 70 | set_head(p, size | PREV_INUSE); 71 | set_foot(p, size); 72 | bck = &av_bin; 73 | fwd = bck->fd; 74 | if (fwd != bck) { 75 | size |= PREV_INUSE; 76 | while ((unsigned long) size < chunksize_nomask(fwd)) 77 | fwd = fwd->fd_nextsize; 78 | if ((unsigned long) size == 79 | (unsigned long) chunksize_nomask(fwd)) 80 | { 81 | p->fd_nextsize = p->bk_nextsize = NULL; 82 | fwd = fwd->fd; 83 | } else { 84 | p->fd_nextsize = fwd; 85 | p->bk_nextsize = fwd->bk_nextsize; 86 | fwd->bk_nextsize = p; 87 | p->bk_nextsize->fd_nextsize = p; 88 | } 89 | bck = fwd->bk; 90 | } else 91 | p->fd_nextsize = p->bk_nextsize = p; 92 | p->bk = bck; 93 | p->fd = fwd; 94 | fwd->bk = p; 95 | bck->fd = p; 96 | } 97 | 98 | static void 99 | malloc_init_state() 100 | { 101 | size_t size; 102 | 103 | av_bin.fd = av_bin.bk = &av_bin; 104 | size = (HEAPSIZE - MIN_CHUNK_SIZE + 2*SIZE_SZ) & ~MALLOC_ALIGN_MASK; 105 | size -= MALLOC_ALIGNMENT; 106 | av_top = (mchunkptr) (heap.bytes + MALLOC_ALIGNMENT - 2*SIZE_SZ); 107 | set_inuse_bit_at_offset(av_top, size); 108 | free_unsorted_chunk(av_top, size); 109 | } 110 | 111 | void * 112 | malloc(size_t bytes) 113 | { 114 | size_t nb, size; 115 | mbinptr bin; 116 | mchunkptr victim, remainder, fwd, bck; 117 | unsigned long remainder_size; 118 | 119 | nb = bytes + SIZE_SZ + MALLOC_ALIGN_MASK; 120 | nb = nb < MINSIZE ? MINSIZE : nb & ~MALLOC_ALIGN_MASK; 121 | if (!(bin = &av_bin)) 122 | malloc_init_state(); 123 | if ((victim = bin->fd) != bin 124 | && (unsigned long) chunksize_nomask(victim) 125 | >= (unsigned long) (nb)) { 126 | victim = victim->bk_nextsize; 127 | while (((unsigned long) (chunksize(victim)) 128 | < (unsigned long) (nb))) 129 | victim = victim->bk_nextsize; 130 | if (victim != bin->bk 131 | && chunksize_nomask(victim) == chunksize_nomask(victim->fd)) 132 | victim = victim->fd; 133 | size = chunksize(victim); 134 | remainder_size = size - nb; 135 | unlink(victim, bck, fwd); 136 | if (remainder_size < MINSIZE) 137 | set_inuse_bit_at_offset(victim, size); 138 | else { 139 | remainder = chunk_at_offset(victim, nb); 140 | set_head(victim, nb | PREV_INUSE); 141 | free_unsorted_chunk(remainder, remainder_size); 142 | } 143 | return chunk2mem(victim); 144 | } 145 | victim = av_top; 146 | size = chunksize(victim); 147 | if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) { 148 | remainder_size = size - nb; 149 | remainder = chunk_at_offset(victim, nb); 150 | av_top = remainder; 151 | set_head(victim, nb | PREV_INUSE); 152 | set_head(remainder, remainder_size | PREV_INUSE); 153 | return chunk2mem(victim); 154 | } 155 | return 0; 156 | } 157 | 158 | void 159 | free(void *mem) 160 | { 161 | mchunkptr p, nextchunk, bck, fwd; 162 | size_t size, nextsize, prevsize; 163 | 164 | p = mem2chunk(mem); 165 | size = chunksize(p); 166 | nextchunk = chunk_at_offset(p, size); 167 | nextsize = chunksize(nextchunk); 168 | if (!prev_inuse(p)) { 169 | prevsize = prev_size(p); 170 | size += prevsize; 171 | p = chunk_at_offset(p, -((long) prevsize)); 172 | unlink(p, bck, fwd); 173 | } 174 | if (nextchunk != av_top) { 175 | if (!inuse_bit_at_offset(nextchunk, nextsize)) { 176 | unlink(nextchunk, bck, fwd); 177 | size += nextsize; 178 | } else 179 | clear_inuse_bit_at_offset(nextchunk, 0); 180 | free_unsorted_chunk(p, size); 181 | } else { 182 | size += nextsize; 183 | set_head(p, size | PREV_INUSE); 184 | av_top = p; 185 | } 186 | } 187 | 188 | 189 | int 190 | main() 191 | { 192 | return 0; 193 | } 194 | -------------------------------------------------------------------------------- /src/qsort/qsort1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define N 666666 4 | double a[N]; 5 | 6 | void 7 | quicksort(int m, int n) 8 | { 9 | int i, j; 10 | double pivot, tmp; 11 | 12 | if (m < n) { 13 | pivot = a[n]; 14 | i = m; j = n; 15 | while (i <= j) { 16 | while (a[i] < pivot) i++; 17 | while (a[j] > pivot) j--; 18 | if (i <= j) { 19 | tmp = a[i]; a[i] = a[j]; a[j] = tmp; 20 | i++; j--; 21 | } 22 | } 23 | quicksort(m, j); 24 | quicksort(i, n); 25 | } 26 | } 27 | 28 | int 29 | main() 30 | { 31 | int i; 32 | 33 | for (i = 0; i < N; i++) 34 | a[i] = i; 35 | quicksort(0, N - 1); 36 | for (i = 0; i < N; i++) 37 | printf("%f\n", a[i]); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /src/qsort/qsort2.c: -------------------------------------------------------------------------------- 1 | int 2 | random(int i, int j) 3 | { 4 | return i + ((j - i) >> 1); 5 | } 6 | 7 | void 8 | exchange(double *_x, double *_y) 9 | { 10 | double z; 11 | 12 | z = *_x; 13 | *_x = *_y; 14 | *_y = z; 15 | } 16 | 17 | void 18 | partition(double *a, int m, int n, int *_i, int *_j) 19 | { 20 | double x; 21 | int f, i, j; 22 | 23 | f = random(m, n); 24 | x = a[f]; 25 | i = m; 26 | j = n; 27 | up: 28 | for (i = i; i <= n; i++) 29 | if (x < a[i]) 30 | goto down; 31 | i = n; 32 | down: 33 | for (j = j; j >= m; j--) 34 | if (a[j] < x) 35 | goto change; 36 | j = m; 37 | change: 38 | if (i < j) { 39 | exchange(&a[i], &a[j]); 40 | i = i + 1; 41 | j = j - 1; 42 | goto up; 43 | } else 44 | if (i < f) { 45 | exchange(&a[i], &a[f]); 46 | i = i + 1; 47 | } else 48 | if (f < j) { 49 | exchange(&a[f], &a[j]); 50 | j = j - 1; 51 | } 52 | *_i = i; 53 | *_j = j; 54 | } 55 | 56 | void 57 | quicksort(double *a, int m, int n) 58 | { 59 | int i, j; 60 | 61 | if (m < n) { 62 | partition(a, m, n, &i, &j); 63 | quicksort(a, m, j); 64 | quicksort(a, i, n); 65 | } 66 | } 67 | 68 | int 69 | main() 70 | { 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /src/qsort/qsort3.c: -------------------------------------------------------------------------------- 1 | #define SWAP(a, b) do { tmp = *a; *a = *b; *b = tmp; } while(0) 2 | 3 | void 4 | quicksort(double *base_ptr, int total_elems) 5 | { 6 | double tmp, *lo, *hi, *left_ptr, *right_ptr, *mid; 7 | 8 | if (total_elems == 0) 9 | return; 10 | lo = base_ptr; 11 | hi = lo + total_elems - 1; 12 | while (lo < hi) { 13 | mid = lo + ((hi - lo) >> 1); 14 | if (*mid < *lo) 15 | SWAP(mid, lo); 16 | if (*hi < *mid) { 17 | SWAP(mid, hi); 18 | if (*mid < *lo) 19 | SWAP(mid, lo); 20 | } 21 | left_ptr = lo + 1; 22 | right_ptr = hi - 1; 23 | do { 24 | while (*left_ptr < *mid) 25 | left_ptr++; 26 | while (*mid < *right_ptr) 27 | right_ptr--; 28 | if (left_ptr < right_ptr) { 29 | SWAP(left_ptr, right_ptr); 30 | if (mid == left_ptr) 31 | mid = right_ptr; 32 | else if (mid == right_ptr) 33 | mid = left_ptr; 34 | left_ptr++; 35 | right_ptr--; 36 | } else if (left_ptr == right_ptr) { 37 | left_ptr++; 38 | right_ptr--; 39 | break; 40 | } 41 | } while (left_ptr <= right_ptr); 42 | if (right_ptr - lo > hi - left_ptr) { 43 | quicksort(left_ptr, hi - left_ptr + 1); 44 | hi = right_ptr; 45 | } else { 46 | quicksort(lo, right_ptr - lo + 1); 47 | lo = left_ptr; 48 | } 49 | } 50 | } 51 | 52 | int 53 | main() 54 | { 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /src/qsort/qsort4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define a(i) (((unsigned char *) base) + i*size) 4 | 5 | void 6 | qsort(void *base, size_t nmemb, size_t size, 7 | int (*compar)(const void *, const void *)) 8 | { 9 | int m, n, i, j; 10 | unsigned char pivot[size], tmp[size]; 11 | 12 | m = 0; 13 | n = nmemb - 1; 14 | if (m < n) { 15 | memcpy(pivot, a(n), size); 16 | i = m; j = n; 17 | while (i <= j) { 18 | while ((*compar)(a(i), pivot) < 0) i++; 19 | while ((*compar)(a(j), pivot) > 0) j--; 20 | if (i <= j) { 21 | memcpy(tmp, a(i), size); 22 | memcpy(a(i), a(j), size); 23 | memcpy(a(j), tmp, size); 24 | i++; j--; 25 | } 26 | } 27 | qsort(a(m), j - m + 1, size, compar); 28 | qsort(a(i), n - i + 1, size, compar); 29 | } 30 | } 31 | 32 | #include 33 | 34 | #define N 666666 35 | double a[N]; 36 | 37 | int 38 | compar_double(const void *p, const void *q) 39 | { 40 | double x = *((double *) p), y = *((double *) q); 41 | return x < y ? -1 : x == y ? 0 : 1; 42 | } 43 | 44 | int 45 | main() 46 | { 47 | int i; 48 | 49 | for (i = 0; i < N; i++) 50 | a[i] = i; 51 | qsort((void *) a, N, sizeof(double), &compar_double); 52 | for (i = 0; i < N; i++) 53 | printf("%f\n", a[i]); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /src/qsort/qsort5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 666666 6 | double a[N]; 7 | 8 | #define THRESHOLD 0x2000 9 | #define THREADS 16 10 | 11 | pthread_mutex_t mutex; 12 | int active = 1; 13 | 14 | void quicksort(int, int, int); 15 | struct quicksort_args {int m; int n;}; 16 | 17 | void * 18 | run_quicksort(void *void_args) 19 | { 20 | struct quicksort_args *args = void_args; 21 | 22 | quicksort(args->m, args->n, 1); 23 | return 0; 24 | } 25 | 26 | void 27 | quicksort(int m, int n, int threaded) 28 | { 29 | int i, j; 30 | double pivot, tmp; 31 | pthread_t thread; 32 | struct quicksort_args args; 33 | 34 | if (m < n) { 35 | pivot = a[n]; 36 | i = m; j = n; 37 | while (i <= j) { 38 | while (a[i] < pivot) i++; 39 | while (a[j] > pivot) j--; 40 | if (i <= j) { 41 | tmp = a[i]; a[i] = a[j]; a[j] = tmp; 42 | i++; j--; 43 | } 44 | } 45 | if (threaded) { 46 | if (n - m < THRESHOLD) 47 | threaded = 0; 48 | else { 49 | pthread_mutex_lock(&mutex); 50 | if (active < THREADS) { 51 | active++; 52 | pthread_mutex_unlock(&mutex); 53 | args.m = m; 54 | args.n = j; 55 | pthread_create(&thread, 0, &run_quicksort, &args); 56 | quicksort(i, n, 1); 57 | pthread_mutex_lock(&mutex); 58 | active--; 59 | pthread_mutex_unlock(&mutex); 60 | pthread_join(thread, 0); 61 | return; 62 | } 63 | pthread_mutex_unlock(&mutex); 64 | } 65 | } 66 | quicksort(m, j, threaded); 67 | quicksort(i, n, threaded); 68 | } 69 | } 70 | 71 | int 72 | main() 73 | { 74 | int i; 75 | 76 | pthread_mutex_init(&mutex, 0); 77 | for (i = 0; i < N; i++) 78 | a[i] = random(); 79 | quicksort(0, N - 1, 1); 80 | for (i = 0; i < N; i++) 81 | printf("%f\n", a[i]); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /src/sqrt/sqrt1.c: -------------------------------------------------------------------------------- 1 | float 2 | sqrt_newton(float x) 3 | { 4 | float y, z; 5 | 6 | if (x <= 0) 7 | return 0; 8 | y = x >= 1 ? x : 1; 9 | do { 10 | z = y; 11 | y = (z + x/z)/2; 12 | } while (y < z); 13 | return y; 14 | } 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int 21 | main() 22 | { 23 | double x, s0; 24 | float s1; 25 | 26 | printf("%18.10f\n", FLT_EPSILON); 27 | for (x = 0.01; x < 100; x += 0.01) { 28 | s0 = sqrt(x); 29 | s1 = sqrt_newton(x); 30 | if (s0 != s1) 31 | printf("%5.2f %12.10Lf\n%18.10Lf\n%18.10f\n", 32 | x, (long double) s0, (long double) s1, s0 - s1); 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /src/sqrt/sqrt2.c: -------------------------------------------------------------------------------- 1 | #define BITS(x) (*((unsigned *) &x)) 2 | #define FLOAT(x) (*((float *) &x)) 3 | 4 | float 5 | sqrt_approx(float x) 6 | { 7 | float one = 1; 8 | unsigned i; 9 | 10 | i = (BITS(x) >> 1) + BITS(one) - (BITS(one) >> 1); 11 | return FLOAT(i); 12 | } 13 | 14 | #include 15 | #include 16 | 17 | int 18 | main() 19 | { 20 | float x, y, z; 21 | 22 | for (x = 1.0; x <= 100.0; x += 1.0) { 23 | y = sqrt(x); 24 | z = sqrt_approx(x); 25 | printf("sqrt(%f) = %f = %f - %f (%f%%)\n", x, y, z, z - y, 100*(z - y)/y); 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /src/sqrt/sqrt3.c: -------------------------------------------------------------------------------- 1 | float 2 | sqrt_approx(float x) 3 | { 4 | union { float x; unsigned i; } u; 5 | 6 | u.x = x; 7 | u.i = (u.i >> 1) + 0x1fc00000; 8 | return u.x; 9 | } 10 | 11 | #include 12 | #include 13 | 14 | int 15 | main() 16 | { 17 | float x, y, z; 18 | 19 | for (x = 1.0; x <= 100.0; x += 1.0) { 20 | y = sqrt(x); 21 | z = sqrt_approx(x); 22 | printf("sqrt(%f) = %f = %f - %f (%f%%)\n", x, y, z, z - y, 100*(z - y)/y); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/sqrt/sqrt4.c: -------------------------------------------------------------------------------- 1 | typedef float SFtype; 2 | 3 | #define FRACBITS 24 4 | #define EXPBITS 8 5 | #define EXPBIAS 127 6 | #define EXPMAX 255 7 | 8 | #define W_TYPE unsigned long 9 | #define I_TYPE long 10 | #define W_TYPE_SIZE 32 11 | 12 | #define CLS_NORMAL 0 13 | #define CLS_ZERO 1 14 | #define CLS_INF 2 15 | #define CLS_NAN 3 16 | 17 | union UNION 18 | { 19 | SFtype flt; 20 | struct STRUCT_LAYOUT 21 | { 22 | unsigned frac:FRACBITS - 1; 23 | unsigned exp:EXPBITS; 24 | unsigned sign:1; 25 | } bits; 26 | }; 27 | 28 | SFtype 29 | __sqrtsf2(SFtype a) 30 | { 31 | SFtype r; 32 | union UNION RAW_flo; 33 | I_TYPE shift; 34 | I_TYPE A_c; 35 | I_TYPE A_s; 36 | I_TYPE A_e; 37 | W_TYPE A_f; 38 | I_TYPE R_c; 39 | I_TYPE R_s; 40 | I_TYPE R_e; 41 | W_TYPE R_f; 42 | W_TYPE S_f; 43 | W_TYPE T_f; 44 | W_TYPE q; 45 | 46 | RAW_flo.flt = a; 47 | A_s = RAW_flo.bits.sign; 48 | A_e = RAW_flo.bits.exp; 49 | A_f = RAW_flo.bits.frac; 50 | switch (A_e) { 51 | default: 52 | A_c = CLS_NORMAL; 53 | A_f |= ((W_TYPE) 1 << (FRACBITS - 1)); 54 | A_f <<= 3; 55 | A_e -= EXPBIAS; 56 | break; 57 | case 0: 58 | if (A_f == 0) 59 | A_c = CLS_ZERO; 60 | else { 61 | shift = __builtin_clzl(A_f); 62 | shift -= (W_TYPE_SIZE - FRACBITS); 63 | A_c = CLS_NORMAL; 64 | A_f <<= (shift + 3); 65 | A_e -= (EXPBIAS - 1 + shift); 66 | } 67 | break; 68 | case EXPMAX: 69 | if (A_f == 0) 70 | A_c = CLS_INF; 71 | else 72 | A_c = CLS_NAN; 73 | break; 74 | } 75 | switch (A_c) { 76 | case CLS_NAN: 77 | R_c = CLS_NAN; 78 | R_s = A_s; 79 | R_f = A_f; 80 | break; 81 | case CLS_INF: 82 | if (A_s) { 83 | R_c = CLS_NAN; 84 | R_s = 1; 85 | R_f = ((W_TYPE) 1 << (FRACBITS - 2)); 86 | } else { 87 | R_c = CLS_INF; 88 | R_s = 0; 89 | } 90 | break; 91 | case CLS_ZERO: 92 | R_c = CLS_ZERO; 93 | R_s = A_s; 94 | break; 95 | case CLS_NORMAL: 96 | if (A_s) { 97 | R_c = CLS_NAN; 98 | R_s = 1; 99 | R_f = ((W_TYPE) 1 << (FRACBITS - 2)); 100 | break; 101 | } 102 | 103 | R_c = CLS_NORMAL; 104 | R_s = 0; 105 | R_e = A_e >> 1; 106 | if (A_e & 1) 107 | A_f += A_f; 108 | S_f = 0; 109 | R_f = 0; 110 | q = ((W_TYPE) 1 << (3 + FRACBITS)) >> 1; 111 | while (q != ((W_TYPE) 1 << 2)) { 112 | T_f = S_f + q; 113 | if (T_f <= A_f) { 114 | S_f = T_f + q; 115 | A_f -= T_f; 116 | R_f += q; 117 | } 118 | A_f += A_f; 119 | q >>= 1; 120 | } 121 | if (A_f) { 122 | if (S_f < A_f) 123 | R_f |= ((W_TYPE) 1 << 2); 124 | R_f |= ((W_TYPE) 1 << 0); 125 | } 126 | 127 | } 128 | switch (R_c) { 129 | case CLS_NORMAL: 130 | R_e += EXPBIAS; 131 | if (R_e > 0) { 132 | if (R_f & 7) { 133 | if ((R_f & 15) != ((W_TYPE) 1 << 2)) 134 | R_f += ((W_TYPE) 1 << 2); 135 | } 136 | if (R_f & ((W_TYPE) 1 << (3 + FRACBITS))) { 137 | R_f &= ~((W_TYPE) 1 << (3 + FRACBITS)); 138 | R_e++; 139 | } 140 | R_f >>= 3; 141 | if (R_e >= EXPMAX) { 142 | R_c = CLS_INF; 143 | R_e = EXPMAX; 144 | R_f = 0; 145 | } 146 | } else { 147 | R_e = -R_e + 1; 148 | if (R_e <= (3 + FRACBITS)) { 149 | R_f = (R_f >> R_e); 150 | if (R_f & 7) { 151 | if ((R_f & 15) != ((W_TYPE) 1 << 2)) 152 | R_f += ((W_TYPE) 1 << 2); 153 | } 154 | if (R_f & (((W_TYPE) 1 << (3 + FRACBITS)) >> 1)) { 155 | R_e = 1; 156 | R_f = 0; 157 | } else { 158 | R_e = 0; 159 | R_f >>= 3; 160 | } 161 | } else { 162 | R_e = 0; 163 | if (R_f != 0) { 164 | R_f = 1; 165 | if ((R_f & 7) && ((R_f & 15) != ((W_TYPE) 1 << 2))) 166 | R_f += ((W_TYPE) 1 << 2); 167 | R_f >>= 3; 168 | } 169 | } 170 | } 171 | break; 172 | case CLS_ZERO: 173 | R_e = 0; 174 | R_f = 0; 175 | break; 176 | case CLS_INF: 177 | R_e = EXPMAX; 178 | R_f = 0; 179 | break; 180 | case CLS_NAN: 181 | R_e = EXPMAX; 182 | R_f |= ((W_TYPE) 1 << (FRACBITS - 2)); 183 | break; 184 | } 185 | RAW_flo.bits.frac = R_f; 186 | RAW_flo.bits.exp = R_e; 187 | RAW_flo.bits.sign = R_s; 188 | r = RAW_flo.flt; 189 | return r; 190 | } 191 | 192 | #include 193 | #include 194 | #include 195 | 196 | int 197 | main() 198 | { 199 | int i; 200 | unsigned long l; 201 | float f, r0, r1; 202 | 203 | i = 1; 204 | for (l = 0; i || l; l++) { 205 | i = 0; 206 | *((unsigned long *) &f) = l; 207 | if (!(l % 1000000)) 208 | fprintf(stderr, "%10lu\n", l); 209 | r0 = sqrt(f); 210 | r1 = __sqrtsf2(f); 211 | if (memcmp(&r0, &r1, sizeof(r0))) { 212 | printf("%f %f %f %08x %08x %08x \n", f, r0, r1, 213 | *((unsigned *) &f), *((unsigned *) &r0), *((unsigned *) &r1)); 214 | fflush(stdout); 215 | } 216 | } 217 | return 0; 218 | } 219 | -------------------------------------------------------------------------------- /src/sqrt/sqrtsf2.c: -------------------------------------------------------------------------------- 1 | /* Software floating-point emulation. 2 | Return sqrt(a) 3 | Copyright (C) 1997-2017 Free Software Foundation, Inc. 4 | This file is part of the GNU C Library. 5 | Contributed by Richard Henderson (rth@cygnus.com) and 6 | Jakub Jelinek (jj@ultra.linux.cz). 7 | 8 | The GNU C Library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | In addition to the permissions in the GNU Lesser General Public 14 | License, the Free Software Foundation gives you unlimited 15 | permission to link the compiled version of this file into 16 | combinations with other programs, and to distribute those 17 | combinations without any restriction coming from the use of this 18 | file. (The Lesser General Public License restrictions do apply in 19 | other respects; for example, they cover modification of the file, 20 | and distribution when not linked into a combine executable.) 21 | 22 | The GNU C Library is distributed in the hope that it will be useful, 23 | but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 | Lesser General Public License for more details. 26 | 27 | You should have received a copy of the GNU Lesser General Public 28 | License along with the GNU C Library; if not, see 29 | . */ 30 | 31 | #include "soft-fp.h" 32 | #include "single.h" 33 | 34 | SFtype 35 | __sqrtsf2 (SFtype a) 36 | { 37 | FP_DECL_EX; 38 | FP_DECL_S (A); 39 | FP_DECL_S (R); 40 | SFtype r; 41 | 42 | FP_INIT_ROUNDMODE; 43 | FP_UNPACK_S (A, a); 44 | FP_SQRT_S (R, A); 45 | FP_PACK_S (r, R); 46 | FP_HANDLE_EXCEPTIONS; 47 | 48 | return r; 49 | } 50 | --------------------------------------------------------------------------------