numbers.k (17540B)
1 ;; check.k & test-helpers.k should be loaded 2 ;; 3 ;; I fixed all of the bugs and added some rationale to some of the tests 4 ;; marked as FAIL. In some cases, as you say, the specification is unclear. 5 ;; In these cases I tried to include my interpretation (which could be wrong), 6 ;; and changed the test to reflect this. 7 ;; 8 ;; I am inclined to wait for the next revision of the report before working 9 ;; too much with numeric features, but some of these could be asked to John 10 ;; Shutt for clarification (but I warn you that while he is very cooperative 11 ;; with this kind of things he sometimes takes a while to answer). 12 ;; 13 ;; The round thing was actually a bug in the IMath division routine 14 ;; I fixed it (I think!) and have sent an email to the maintainer to 15 ;; report the bug and hopefully confirm the correctness of the fix 16 ;; 17 ;; Andres Navarro 18 ;; 19 ;; Please look for the keyword FAIL in the source code. 20 ;; The marked lines include 21 ;; - failing tests 22 ;; - tests corresponding to incorrect or unclear specification 23 ;; 24 ;; Other bugs: 25 ;; 26 ;; - evaluating 27 ;; 28 ;; ($check equal? (round -1.1) -1) 29 ;; freezes the interpreter 30 ;; 31 32 ;; 12.4 External representation of numbers. 33 ;; 34 ;; check various formats against plain decimals 35 ;; 36 37 ($check equal? #d000 0) 38 ($check equal? #d099 99) 39 ($check equal? #d-099 -99) 40 ($check equal? #d35/67 35/67) 41 42 ($check equal? #x00 0) 43 ($check equal? #x0FF 255) 44 ($check equal? #x-0FF -255) 45 ($check equal? #x-AB/CD -171/205) 46 47 ($check equal? #b00000 0) 48 ($check equal? #b01111 15) 49 ($check equal? #b-01111 -15) 50 ($check equal? #b#e101 5) 51 52 ($check equal? #o0000 0) 53 ($check equal? #o0777 511) 54 ($check equal? #o-0777 -511) 55 ($check equal? #e#o-16 -14) 56 57 ($check equal? #e-infinity #e-infinity) 58 ($check equal? #e+infinity #e+infinity) 59 ($check equal? #i-infinity #i-infinity) 60 ($check equal? #i+infinity #i+infinity) 61 62 ;; 12.5.1 number? finite? integer? 63 ($check-predicate (number? 0 1 3/5 -3.14e0 #real)) 64 ($check-not-predicate (number? 5 "6" 7)) 65 66 ($check-predicate (finite? 0 1/3 -99999999)) 67 ($check-not-predicate (finite? #e+infinity)) 68 ($check-not-predicate (finite? #e-infinity)) 69 70 ($check-error (finite? #real)) 71 ($check-error (finite? #undefined)) 72 73 ($check-predicate (integer? 0 8/2 -12/6 1.0 -1.25e2)) 74 ($check-not-predicate (integer? #e+infinity)) 75 ($check-not-predicate (integer? #e-infinity)) 76 ($check-not-predicate (integer? #real)) 77 ($check-not-predicate (integer? "0")) 78 79 ;; 12.?? exact-integer? 80 ($check-predicate (exact-integer? 0 8/2 -12/6)) 81 ($check-not-predicate (exact-integer? 1.0)) 82 ($check-not-predicate (exact-integer? #e+infinity)) 83 ($check-not-predicate (exact-integer? #e-infinity)) 84 ($check-not-predicate (exact-integer? #real)) 85 ($check-not-predicate (exact-integer? "0")) 86 87 88 ;; 12.5.2 =? 89 90 ($check-predicate (=?)) 91 ($check-predicate (=? -1)) 92 ($check-predicate (=? 0 0.0 0/1 -0.0 -0/1)) 93 ($check-predicate (=? #e+infinity #e+infinity)) 94 ($check-predicate (=? #e-infinity #e-infinity)) 95 ($check-predicate (=? . #0=(1 . #0#))) 96 ($check-not-predicate (=? 0 1)) 97 ($check-not-predicate (=? 1 #e-infinity)) 98 ($check-not-predicate (=? #e+infinity #e-infinity)) 99 ($check-not-predicate (=? 2 5/2)) 100 ($check-not-predicate (=? . #0=(1 2 . #0#))) 101 ($check-error (=? 0 #f)) 102 ($check-error (=? 1 #t)) 103 ($check-error (=? #real #real)) 104 ($check-error (=? 1 #real)) 105 ($check-error (=? #real -1/2)) 106 ($check-error (=? #real #e+infinity)) 107 108 ;; 12.5.3 <? <=? >=? >? 109 110 ($check-predicate (<?)) 111 ($check-predicate (<? 1)) 112 ($check-predicate (<? 1 3 7 15)) 113 ($check-not-predicate (<? 1 7 3 7 15)) 114 ($check-predicate (<? #e-infinity -1 0 1 #e+infinity)) 115 116 ;; 12.5.4 + 117 118 ($check equal? (+ 1 1) 2) 119 ($check equal? (+) 0) 120 ($check equal? (+ . #0=(0 . #0#)) 0) 121 ($check equal? (+ . #0=(1 . #0#)) #e+infinity) 122 ($check equal? (+ . #0=(-1 . #0#)) #e-infinity) 123 ($check equal? (+ . #0=(1 -1 . #0#)) #real) 124 125 ;; 12.5.5 * 126 127 ($check equal? (* 2 3) 6) 128 ($check equal? (*) 1) 129 ($check equal? (* 0 #e+infinity) #real) 130 ($check equal? (* 0 #e-infinity) #real) 131 ($check equal? (* . #0=(1 . #0#)) 1) 132 ($check equal? (* . #0=(2 . #0#)) #e+infinity) 133 ($check equal? (* . #0=(1/2 . #0#)) 0) 134 ($check equal? (* . #0=(1/2 2 . #0#)) #real) 135 ($check equal? (* . #0=(-1 . #0#)) #real) 136 137 ;; 12.5.5 - 138 139 ($check equal? (- 5 3) 2) 140 ($check-error (-)) 141 ($check-error (- 0)) 142 143 ;; 12.5.7 zero? 144 145 ($check-predicate (zero? 0 0/1 -0 -0/1 0.0 -0.0 #i0)) 146 ($check-not-predicate (zero? 1)) 147 ($check-not-predicate (zero? -0.0001)) 148 ($check-not-predicate (zero? #e+infinity)) 149 ($check-not-predicate (zero? #e-infinity)) 150 ($check-error (zero? #real)) 151 ($check-error (zero? #undefined)) 152 153 ;; 12.5.8 div, mod, div-and-mod 154 155 ($check equal? (div 10 2) 5) 156 ($check equal? (div -10 2) -5) 157 ($check equal? (div 10 -2) -5) 158 ($check equal? (div -10 -2) 5) 159 160 ($check equal? (div 10 7) 1) 161 ($check equal? (div -10 7) -2) 162 163 ;; (div real1 real2) ... Let n be the greatest integer such that 164 ;; real2 * n <= real1. Applicative div returns n. 165 ;; 166 ;; If real2 is negative, then such integer n does not exist. 167 ;; interpretation : result shall be #undefined 168 ;; 169 ;; I followed Scheme r6rs and r7rs draft here. The definition in the 170 ;; Kernel report didn't make much sense to me. I'm still waiting the 171 ;; next installement of the report to see if this is changed. 172 ;; 173 ;; Andres Navarro 174 ;--- ($check equal? (div 10 -7) #undefined) ; FAIL 175 ;--- ($check equal? (div -10 -7) #undefined) ; FAIL 176 177 ($check equal? (mod 10 7) 3) 178 ($check equal? (div-and-mod 10 7) (list 1 3)) 179 180 ;; 12.5.9 div0, mod0, div-and-mod0 181 ;; Test cases from R6RS. The commented test cases 182 ;; contradict the KernelReport. 183 184 ($check equal? (div-and-mod 123 10) (list 12 3)) 185 ;----- ($check equal? (div-and-mod 123 -10) (list -12 3)) 186 ($check equal? (div-and-mod -123 10) (list -13 7)) 187 ;----- ($check equal? (div-and-mod -123 -10) (list 13 7)) 188 ($check equal? (div0-and-mod0 123 10) (list 12 3)) 189 ;----- ($check equal? (div0-and-mod0 123 -10) (list -12 3)) 190 ($check equal? (div0-and-mod0 -123 10) (list -12 -3)) 191 ;----- ($check equal? (div0-and-mod0 -123 -10) (list 12 -3)) 192 193 ;; 12.5.10 positive? negative? 194 195 ($check-predicate (positive? 1 1.0 1/1 999999999999 #e+infinity)) 196 ($check-not-predicate (positive? 0)) 197 ($check-not-predicate (positive? #e-infinity)) 198 ($check-error (positive? #real)) 199 ($check-error (positive? #undefined)) 200 201 ($check-predicate (negative? -1 -1.0 -1/1 -999999999999 #e-infinity)) 202 ($check-not-predicate (negative? 0)) 203 ($check-not-predicate (negative? #e+infinity)) 204 ($check-error (negative? #real)) 205 ($check-error (negative? #undefined)) 206 207 ;; 12.5.11 even? odd? 208 209 ($check-predicate (even? 0 2 -2 4/2 9999999999998)) 210 ($check-error (even? #e+infinity)) 211 ($check-error (even? #e-infinity)) 212 213 ($check-predicate (odd? 1 -1 6/2 9999999999999)) 214 ($check-error (odd? #e+infinity)) 215 ($check-error (odd? #e-infinity)) 216 217 ;; 12.5.12 abs 218 219 ($check equal? (abs 0) 0) 220 ($check equal? (abs 1) 1) 221 ($check equal? (abs -1) 1) 222 ($check equal? (abs #e+infinity) #e+infinity) 223 ($check equal? (abs #e-infinity) #e+infinity) 224 225 ;; 12.5.12 max min 226 227 ($check equal? (max) #e-infinity) 228 ($check equal? (max 1 2 3 4) 4) 229 ($check equal? (max #e-infinity #e+infinity) #e+infinity) 230 231 ($check equal? (min) #e+infinity) 232 ($check equal? (min 1 2 3 4) 1) 233 ($check equal? (min #e-infinity #e+infinity) #e-infinity) 234 235 ;; 12.5.12 lcm gcd 236 ;; TODO 237 238 ;; 12.6.1 exact? inexact? robust? undefined? 239 240 ($check-predicate (exact? 0 1 -1 1/2 999999999999 #e-infinity)) 241 ($check-not-predicate (exact? 3.14)) 242 ($check-not-predicate (exact? #i-infinity)) 243 ($check-not-predicate (exact? #real)) 244 ($check-not-predicate (exact? #undefined)) 245 246 ($check-predicate (inexact? #real 3.14 #undefined #i+infinity)) 247 ($check-not-predicate (inexact? 0)) 248 ($check-not-predicate (inexact? #e+infinity)) 249 250 ($check-predicate (robust? 0 1 -1 1/3 999999999999 #e-infinity #e+infinity)) 251 ;; For now klisp doesn't support precise bounds or robust tagging of inexact 252 ;; numbers. This is, however, allowed by the report (see section 12.2, 253 ;; Inexactness): 254 ;; 255 ;; "(...) The implementation might simply take all inexact real numbers 256 ;; to be non-robust with upper bound positive infinity and lower bound 257 ;; negative infinity (...)" 258 ;; 259 ;; Andres Navarro 260 ;; was ($check-predicate (robust? 3.14)) ; FAIL 261 ($check-not-predicate (robust? #real)) 262 ($check-not-predicate (robust? #undefined)) 263 264 ($check-predicate (undefined? #undefined)) 265 ($check-not-predicate (undefined? 0)) 266 267 ;; 12.6.2 get-real-internal-bounds get-real-exact-bounds 268 ;; TODO: How to test it? 269 ($check equal? (get-real-internal-bounds 0) (list 0 0)) 270 ($check equal? (get-real-exact-bounds 0) (list 0 0)) 271 272 ;; 12.6.3 get-real-internal-primary get-real-exact-primary 273 ;; TODO: How to test it? 274 275 ;; 12.6.4 make-inexact 276 ;; TODO 277 278 ;; 12.6.5 real->inexact real->exact 279 ;; TODO 280 281 ;; 12.6.6 with-strict-arithmetic get-strict-arithmetic? 282 ;; TODO 283 284 ;; 12.7.1 with-narrow-arithmetic get-narrow-arithmetic? 285 ;; TODO 286 287 ;; 12.8.1 rational? 288 289 ($check-predicate (rational? 0 1 1/2)) 290 ;; For now (and probably forever) klisp doesn't support non-rational 291 ;; reals. While this is certainly doable it implies the use of a complex 292 ;; algebraic module that is well beyond the scope of this project. 293 ;; See following paragraph from the report: "It would seem a daunting task to 294 ;; implement module Real without module Inexact, but in case someone has a 295 ;; reason to do so, the report doesn’t preclude it, i.e., module Real doesn’t 296 ;; assume module Inexact." 297 ;; 298 ;; Then, in section 12.2, Inexactness, it says: " However, sometimes 299 ;; there may be no way for an internal number to capture a mathematical 300 ;; number that the client wants to reason about, either because the intended 301 ;; mathematical number cannot be represented by an internal number (as with 302 ;; exclusively rational internal number formats confronted with an irrational 303 ;; mathematical number) ..." 304 ;; and then on the definition of rational? (12.8.1) 305 ;; "An inexact real is a rational iff its primary value is a ratio of 306 ;; integers." which is true of all finite reals supported by klisp 307 ;; as they are represented in floating point format and are therefore 308 ;; expressible by the formula (sign + or -) mantissa / 2 ^ (-expt) 309 ;; 310 ;; Andres Navarro 311 ; was ($check-not-predicate (rational? (sqrt 2))) ; FAIL 312 ($check-not-predicate (rational? #e+infinity)) 313 314 ;; 12.8.2 / 315 316 ($check equal? (/ 2 3) 2/3) 317 ($check equal? (/ 1 2 3) 1/6) 318 ($check-error (/ 1 0)) 319 ($check-error (/ #e+infinity #e+infinity)) 320 321 ;; 12.8.3 numerator denominator 322 323 ($check equal? (numerator 3/4) 3) 324 ($check equal? (numerator -3/4) -3) 325 ($check equal? (denominator 3/4) 4) 326 ($check equal? (denominator -3/4) 4) 327 328 ;; 12.8.4 floor ceiling truncate bound 329 330 ;; By my interpretation of the report, these applicatives return inexact 331 ;; integers (they could in principle return exact integers if the reals 332 ;; passed were correctly bounded, and this is the case in klisp for exact 333 ;; rationals for example, but not for inexact reals in general). The report 334 ;; only says that exact arguments means exact results (when possible). 335 ;; I could be wrong of course, I should consult this with John Shutt 336 ;; 337 ;; Andres Navarro 338 339 ($check equal? (floor 0) 0) 340 ($check equal? (floor #e1.23) 1) 341 ($check equal? (floor #e-1.23) -2) 342 ($check =? (floor 1.23) 1) 343 ($check =? (floor -1.23) -2) 344 345 ($check equal? (ceiling 0) 0) 346 ($check equal? (ceiling #e1.23) 2) 347 ($check equal? (ceiling #e-1.23) -1) 348 ($check =? (ceiling 1.23) 2) 349 ($check =? (ceiling -1.23) -1) 350 351 ($check equal? (truncate 0) 0) 352 ($check equal? (truncate #e1.99) 1) 353 ($check equal? (truncate #e-1.99) -1) 354 ($check =? (truncate 1.99) 1) 355 ($check =? (truncate -1.99) -1) 356 357 ($check equal? (round 0) 0) 358 ($check equal? (round 1/2) 0) 359 ($check equal? (round #e1.1) 1) 360 ($check =? (round 1.1) 1) 361 ($check equal? (round 3/2) 2) 362 ($check equal? (round #e1.9) 2) 363 ($check =? (round 1.9) 2) 364 ($check equal? (round -1/2) 0) 365 ($check =? (round #e-1.1) -1) 366 ($check equal? (round #e-1.1) -1) 367 ($check equal? (round -3/2) -2) 368 ($check equal? (round #e-1.9) -2) 369 ($check =? (round -1.9) -2) 370 371 ;; 12.8.5 rationalize simplest-rational 372 373 ($check equal? (rationalize 0 1) 0) 374 375 ;; I would think the same as for floor, truncate, etc apply here 376 ;; Here the reports even says this explicitly, in 12.8.5: 377 ;; "If real1 and real2 are exact, the applicative (whichever it is) 378 ;; returns exact x0. If one or both of real1 and real2 are inexact, 379 ;; the applicative returns an inexact approximating x0 380 ;; (as by real->inexact , §12.6.5). 381 ;; 382 ;; Andres Navarro 383 384 ;; (I think you meant 1/7 here, 1/6 is about 0.16, and so, outside the range) 385 ;; 386 ;; Andres Navarro 387 ;; was ($check equal? (rationalize 0.1 0.05) 1/6) ; FAIL 388 ($check =? (rationalize 0.1 0.05) 1/7) 389 ($check equal? (rationalize #e0.1 #e0.05) 1/7) 390 391 ($check equal? (simplest-rational 2/7 3/5) 1/2) 392 ($check =? (simplest-rational 0.1 0.3) 1/4) 393 ($check equal? (simplest-rational #e0.1 #e0.3) 1/4) 394 395 ;; 12.9.1 real? 396 397 ($check-predicate (real? 0 1 -1 1/2 999999999999 #e-infinity)) 398 ($check-not-predicate (real? #undefined)) 399 400 ;; 12.9.2 exp log 401 ;; These functions are not described in the Report, but let us try... 402 403 ($check equal? (exp 0.0) 1.0) 404 ($check equal? (log 1.0) 0.0) 405 406 ;; 12.9.2 sin cos tan 407 ($check equal? (sin 0.0) 0.0) 408 ($check equal? (cos 0.0) 1.0) 409 ($check equal? (tan 0.0) 0.0) 410 411 ;; 12.9.2 asin acos atan 412 ($check equal? (asin 0.0) 0.0) 413 ($check equal? (acos 1.0) 0.0) 414 ($check equal? (atan 0.0) 0.0) 415 416 ;; 12.9.5 sqrt 417 ($check equal? (sqrt 0.0) 0.0) 418 ($check equal? (sqrt 1.0) 1.0) 419 ($check equal? (sqrt 4.0) 2.0) 420 421 ;; 12.9.6 expt 422 ($check equal? (expt 2.0 4.0) 16.0) 423 424 ;; 12.10 Complex features 425 ;; not implemented 426 427 ;; String conversion 428 429 ;; 12.? number->string 430 ($check string-ci=? (number->string 0) "0") 431 ($check string-ci=? (number->string 1) "1") 432 ($check string-ci=? (number->string -1) "-1") 433 ($check string-ci=? (number->string 2 2) "10") 434 ($check string-ci=? (number->string -2 2) "-10") 435 ($check string-ci=? (number->string 8 8) "10") 436 ($check string-ci=? (number->string -8 8) "-10") 437 ($check string-ci=? (number->string 10 10) "10") 438 ($check string-ci=? (number->string -10 10) "-10") 439 ($check string-ci=? (number->string 16 16) "10") 440 ($check string-ci=? (number->string -16 16) "-10") 441 ; default base 442 ($check string-ci=? (number->string 10) (number->string 10 10)) 443 ;; infinities, undefined and reals with no primary value 444 ($check string-ci=? (number->string #undefined) "#undefined") 445 ($check string-ci=? (number->string #real) "#real") 446 ($check string-ci=? (number->string #e+infinity) "#e+infinity") 447 ($check string-ci=? (number->string #e-infinity) "#e-infinity") 448 ($check string-ci=? (number->string #i+infinity) "#i+infinity") 449 ($check string-ci=? (number->string #i-infinity) "#i-infinity") 450 ;; rationals 451 ($check string-ci=? (number->string 13/17) "13/17") 452 ($check string-ci=? (number->string -17/13) "-17/13") 453 ($check string-ci=? (number->string #o-21/15 8) "-21/15") 454 ;; bigints 455 ($check string-ci=? (number->string #x1234567890abcdef 16) 456 "1234567890abcdef") 457 458 ; only bases 2, 8, 10, 16 459 ($check-error (number->string 10 3)) 460 ; only numbers 461 ($check-error (number->string #inert)) 462 ($check-error (number->string #inert 2)) 463 ; only numbers 464 ($check-error (number->string "2")) 465 ($check-error (number->string "2" 8)) 466 ; only base 10 with inexact numbers 467 ($check-error (number->string -1.0 2)) 468 ($check-error (number->string 1.25 8)) 469 ($check-error (number->string 3.0 16)) 470 471 ;; 12.? string->number 472 ($check =? (string->number "0") 0) 473 ($check =? (string->number "1") 1) 474 ($check =? (string->number "-1") -1) 475 ($check =? (string->number "10" 2) 2) 476 ($check =? (string->number "-10" 2) -2) 477 ($check =? (string->number "10" 8) 8) 478 ($check =? (string->number "-10" 8) -8) 479 ($check =? (string->number "10" 10) 10) 480 ($check =? (string->number "-10" 10) -10) 481 ($check =? (string->number "10" 16) 16) 482 ($check =? (string->number "-10" 16) -16) 483 ; default base 484 ($check =? (string->number "10") (string->number "10" 10)) 485 ;; infinities, undefined and reals with no primary value 486 ;; #undefined and #real can't be compared with =? 487 ($check equal? (string->number "#undefined") #undefined) 488 ($check equal? (string->number "#real") #real) 489 ($check =? (string->number "#e+infinity") #e+infinity) 490 ($check =? (string->number "#e-infinity") #e-infinity) 491 ($check =? (string->number "#i+infinity") #i+infinity) 492 ($check =? (string->number "#i-infinity") #i-infinity) 493 ;; rationals 494 ($check =? (string->number "13/17") 13/17) 495 ($check =? (string->number "-17/13") -17/13) 496 ($check =? (string->number "-21/15" 8) #o-21/15) 497 ;; bigints 498 ($check =? (string->number "1234567890abcdef" 16) 499 #x1234567890abcdef) 500 ($check =? (string->number "1234567890ABCDEF" 16) 501 #x1234567890abcdef) 502 ;; doubles 503 ($check =? (string->number "1.25e10") 1.25e10) 504 ($check =? (string->number "-1.25e10" 10) -1.25e10) 505 506 ; only bases 2, 8, 10, 16 507 ($check-error (string->number "10" 3)) 508 ; only strings 509 ($check-error (string->number #inert)) 510 ($check-error (string->number #inert 2)) 511 ($check-error (string->number 2)) 512 ($check-error (string->number 2 8)) 513 ; only base 10 with inexact numbers 514 ($check-error (string->number "-1.0" 2)) 515 ($check-error (string->number "1.25" 8)) 516 ($check-error (string->number "3.0" 16))