/src/lib/numeric/integral.e
Specman e | 581 lines | 352 code | 69 blank | 160 comment | 0 complexity | 4c157ff13ecacb916dfd25fc66e54d1c MD5 | raw file
1-- This file is part of a Liberty Eiffel library. 2-- See the full copyright at the end. 3-- 4deferred class INTEGRAL 5 -- 6 -- General integer abstraction for both integers and naturals. 7 -- 8 9inherit 10 COMPARABLE 11 undefine infix "<=", infix ">", infix ">=", is_equal 12 end 13 14insert 15 NUMERIC 16 PLATFORM 17 18feature {ANY} 19 infix "+" (other: like Current): like Current 20 require 21 no_overflow: Current > zero = (other > zero) implies Current #+ other > zero = (Current > zero) -- this means: if operand are of same sign, it will be sign of the Result. 22 deferred 23 ensure 24 Result #- other = Current 25 end 26 27 infix "-" (other: like Current): like Current 28 require 29 no_overflow: Current > zero /= (other > zero) implies Current #- other > zero = (Current > zero) -- this means: if operand are of different sign, sign of the Result will be the same sign as Current. 30 deferred 31 ensure 32 Result #+ other = Current 33 end 34 35 infix "*" (other: like Current): like Current 36 require 37 no_overflow: (other /= zero) implies Current #* other #// other = Current 38 deferred 39 ensure 40 Current /= zero and other /= zero implies Result /= zero 41 Result /= zero implies Result #// other = Current 42 Result /= zero implies Result #\\ other = zero 43 end 44 45 infix "/" (other: like Current): REAL 46 deferred 47 end 48 49 infix "//" (other: like Current): like Current 50 -- Quotient of the Euclidian division of `Current' by `other'. 51 -- The corresponding remainder is given by infix "\\". 52 -- 53 -- See also infix "#//". 54 require 55 other /= zero 56 no_overflow: other = -one implies Current = zero or Current |<< 1 /= zero 57 deferred 58 ensure 59 euclidian_divide_case1: Current >= zero implies Result * other + Current \\ other = Current 60 euclidian_divide_case2: Current < zero implies Result #* other #+ (Current \\ other) = Current 61 end 62 63 infix "\\" (other: like Current): like Current 64 -- Remainder of the Euclidian division of `Current' by `other'. 65 -- By definition, `zero <= Result < other.abs'. 66 -- 67 -- See also infix "#\\", infix "//". 68 require 69 other /= zero 70 deferred 71 ensure 72 Result >= zero 73 other |<< 1 /= zero implies Result < other.abs 74 good_remainder: Result #- (Current #\\ other) #\\ other = zero 75 end 76 77 infix "^" (exp: like Current): INTEGER_64 78 -- Integer power of `Current' by `other' 79 require 80 exp >= zero 81 deferred 82 end 83 84 abs: like Current 85 -- Absolute value of `Current'. 86 require 87 not_minimum_value: Current < zero implies zero < #-Current 88 deferred 89 ensure 90 Result >= zero 91 end 92 93 infix "<" (other: like Current): BOOLEAN 94 deferred 95 end 96 97 infix "<=" (other: like Current): BOOLEAN 98 deferred 99 end 100 101 infix ">" (other: like Current): BOOLEAN 102 deferred 103 end 104 105 infix ">=" (other: like Current): BOOLEAN 106 deferred 107 end 108 109 prefix "+": like Current 110 deferred 111 end 112 113 prefix "-": like Current 114 require 115 not_minimum_value: Current < zero implies zero < #-Current 116 deferred 117 end 118 119 is_odd: BOOLEAN 120 -- Is odd? 121 deferred 122 end 123 124 is_even: BOOLEAN 125 -- Is even? 126 deferred 127 end 128 129 sqrt: REAL 130 -- Square root of `Current'. 131 require 132 Current >= zero 133 deferred 134 end 135 136 log: REAL 137 -- Natural Logarithm of `Current'. 138 require 139 Current > zero 140 deferred 141 end 142 143 log10: REAL 144 -- Base-10 Logarithm of Current. 145 require 146 Current > zero 147 deferred 148 end 149 150 gcd (other: like Current): like Current 151 -- Greatest Common Divisor of `Current' and `other'. 152 deferred 153 ensure 154 Result >= zero 155 Result = zero implies Current = zero and other = zero 156 Result >= (one + one) implies Current \\ Result = zero and other \\ Result = zero and (Current // Result).gcd(other // Result) = one 157 end 158 159 lcm (other: like Current): like Current 160 -- Least Common Multiple of `Current' and `other'. 161 do 162 Result := abs // gcd(other) * other.abs 163 ensure 164 Result >= zero 165 Result = zero implies Current = zero or other = zero 166 Result * gcd(other) = (Current * other).abs 167 end 168 169feature {ANY} -- Conversions: 170 to_string: STRING 171 -- The decimal view of `Current' into a new allocated STRING. 172 -- For example, if `Current' is -1 the `Result' is "-1". 173 -- 174 -- See also `append_in', `to_string_format', `to_unicode_string', `to_hexadecimal', `to_octal'. 175 deferred 176 end 177 178 to_unicode_string: UNICODE_STRING 179 -- The decimal view of `Current' into a new allocated UNICODE_STRING. 180 -- For example, if `Current' is -1 the `Result' is U"-1". 181 -- 182 -- See also `append_in_unicode', `to_unicode_string_format', `to_string', `to_hexadecimal', `to_octal'. 183 deferred 184 end 185 186 to_boolean: BOOLEAN 187 -- Return False for 0, otherwise True. 188 -- 189 -- See also `to_string', `to_character', `to_hexadecimal', `to_number'. 190 deferred 191 ensure 192 Result = (Current /= zero) 193 end 194 195 to_number: NUMBER 196 -- Convert `Current' into a new allocated NUMBER. 197 -- 198 -- See also `to_boolean', `to_string', `to_character', `to_hexadecimal'. 199 deferred 200 ensure 201 Result.to_string.is_equal(to_string) 202 end 203 204 append_in (buffer: STRING) 205 -- Append in the `buffer' the equivalent of `to_string'. 206 -- If you look for performances, you should always prefer `append_in' which allow you to recycle 207 -- a unique common `buffer' (each call of `to_string' allocate a new object!). 208 -- 209 -- See also `append_in_format', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'. 210 require 211 buffer /= Void 212 deferred 213 end 214 215 append_in_unicode (buffer: UNICODE_STRING) 216 -- Append in the `buffer' the equivalent of `to_unicode_string'. 217 -- If you look for performances, you should always prefer `append_in_unicode' which allow you to recycle 218 -- a unique common `buffer' (each call of `to_unicode_string' allocate a new object!). 219 -- 220 -- See also `append_in_unicode_format', `append_in', `append_in_format', `to_hexadecimal_in'. 221 require 222 buffer /= Void 223 deferred 224 end 225 226 to_string_format (s: INTEGER): STRING 227 -- Same as `to_string' but the result is on `s' character and the number is right aligned. 228 -- 229 -- See also `append_in_format', `to_character', `to_number', `to_hexadecimal'. 230 require 231 to_string.count <= s 232 deferred 233 ensure 234 Result.count = s 235 end 236 237 to_unicode_string_format (s: INTEGER): UNICODE_STRING 238 -- Same as `to_unicode_string' but the result is on `s' character and the number is right aligned. 239 -- 240 -- See also `append_in_unicode_format', `to_string', `to_hexadecimal', `to_octal'. 241 require 242 to_string.count <= s 243 deferred 244 ensure 245 Result.count = s 246 end 247 248 append_in_format (buffer: STRING; s: INTEGER) 249 -- Append in the `buffer' the equivalent of `to_string_format'. 250 -- If you look for performances, you should always prefer `append_in_format' which allow you to recycle 251 -- a unique common `buffer' (each call of `to_string_format' allocate a new object!). 252 -- 253 -- See also `append_in', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'. 254 require 255 to_string.count <= s 256 deferred 257 ensure 258 buffer.count >= old buffer.count + s 259 end 260 261 append_in_unicode_format (buffer: UNICODE_STRING; s: INTEGER) 262 -- Append in the `buffer' the equivalent of `to_unicode_string_format'. 263 -- If you look for performances, you should always prefer `append_in_unicode_format' which allow you to recycle 264 -- a unique common `buffer' (each call of `to_unicode_string_format' allocate a new object!). 265 -- 266 -- See also `append_in_format', `append_in', `append_in_format', `to_hexadecimal_in'. 267 require 268 to_string.count <= s 269 deferred 270 ensure 271 buffer.count >= old buffer.count + s 272 end 273 274 digit: CHARACTER 275 -- Legacy synonym for `decimal_digit'. 276 -- Note: already prefer `decimal_digit' because digit may become obsolete (feb 4th 2006). 277 deferred 278 ensure 279 Result = decimal_digit 280 end 281 282 is_decimal_digit: BOOLEAN 283 deferred 284 end 285 286 decimal_digit: CHARACTER 287 -- Gives the corresponding CHARACTER for range 0..9. 288 require 289 is_decimal_digit 290 deferred 291 ensure 292 (once "0123456789").has(Result) 293 --Current.is_equal(Result.value) 294 end 295 296 is_hexadecimal_digit: BOOLEAN 297 deferred 298 end 299 300 hexadecimal_digit: CHARACTER 301 -- Gives the corresponding CHARACTER for range 0..15. 302 require 303 is_hexadecimal_digit 304 deferred 305 ensure 306 (once "0123456789ABCDEF").has(Result) 307 end 308 309 to_character: CHARACTER 310 -- Return the corresponding ASCII character. 311 -- 312 -- See also `to_boolean', `to_number', `to_string', `to_hexadecimal'. 313 require 314 Current >= zero 315 --Current <= Maximum_character_code 316 deferred 317 end 318 319 to_octal_in (buffer: STRING) 320 -- Append in the `buffer' the equivalent of `to_octal'. 321 -- If you look for performances, you should always prefer `to_octal_in' which allow you to recycle 322 -- a unique common `buffer' (each call of `to_octal' allocate a new object!). 323 -- 324 -- See also `to_hexadecimal_in', `append_in', `append_in_format', `append_in_unicode'. 325 deferred 326 ensure 327 buffer.count = old buffer.count + bit_count #// 3 + 1 328 end 329 330 to_octal: STRING 331 -- The octal view of `Current' into a new allocated STRING. 332 -- For example, if `Current' is -1 and if `Current' is a 16 bits integer the `Result' is "177777". 333 -- 334 -- See also `to_octal_in', `to_hexadecimal', `to_number', `to_string'. 335 deferred 336 ensure 337 Result.count = bit_count #// 3 + 1 338 end 339 340 to_hexadecimal: STRING 341 -- The hexadecimal view of `Current' into a new allocated STRING. 342 -- For example, if `Current' is -1 and if `Current' is a 32 bits integer the `Result' is "FFFFFFFF". 343 -- 344 -- See also `to_hexadecimal_in', `to_octal', `to_number', `to_string'. 345 deferred 346 ensure 347 Result.count = object_size * 2 348 end 349 350 to_hexadecimal_in (buffer: STRING) 351 -- Append in the `buffer' the equivalent of `to_hexadecimal'. 352 -- If you look for performances, you should always prefer `to_hexadecimal_in' which allow you to recycle 353 -- a unique common `buffer' (each call of `to_hexadecimal' allocate a new object!). 354 -- 355 -- See also `to_octal_in', `append_in', `append_in_format', `append_in_unicode'. 356 deferred 357 ensure 358 buffer.count = old buffer.count + object_size * 2 359 end 360 361feature {ANY} -- Bitwise Logical Operators: 362 bit_test (idx: INTEGER_8): BOOLEAN 363 -- The value of the `idx'-ith bit (the right-most bit is at index 0). 364 require 365 idx.in_range(0, bit_count - 1) 366 deferred 367 end 368 369 bit_set (idx: INTEGER_8): like Current 370 -- The value of the `idx'-ith bit (the right-most bit is at index 0). 371 require 372 idx.in_range(0, bit_count - 1) 373 deferred 374 ensure 375 Result.bit_test(idx) 376 Result = Current or Result.bit_reset(idx) = Current 377 end 378 379 bit_reset (idx: INTEGER_8): like Current 380 -- The value of the `idx'-ith bit (the right-most bit is at index 0). 381 require 382 idx.in_range(0, bit_count - 1) 383 deferred 384 ensure 385 not Result.bit_test(idx) 386 Result = Current or Result.bit_set(idx) = Current 387 end 388 389 infix "|>>", bit_shift_right (s: INTEGER_8): like Current 390 -- Shift by `s' positions right (sign bit copied) bits falling off the end are lost. 391 require 392 s.in_range(0, bit_count - 1) 393 deferred 394 end 395 396 infix "|>>>", bit_shift_right_unsigned (s: INTEGER_8): like Current 397 -- Shift by `s' positions right (sign bit not copied) bits falling off the end are lost. 398 require 399 s.in_range(0, bit_count - 1) 400 deferred 401 end 402 403 infix "|<<", bit_shift_left (s: INTEGER_8): like Current 404 -- Shift by `s' positions left bits falling off the end are lost. 405 require 406 s.in_range(0, bit_count - 1) 407 deferred 408 end 409 410 infix "#>>", bit_rotate_right (s: INTEGER_8): like Current 411 -- Rotate by `s' positions right. 412 -- 413 -- See also `bit_rotate_left' and `bit_rotate'. 414 require 415 s.in_range(1, bit_count - 1) 416 deferred 417 end 418 419 infix "#<<", bit_rotate_left (s: INTEGER_8): like Current 420 -- Rotate by `s' positions left. 421 -- 422 -- See also `bit_rotate_right' and `bit_rotate'. 423 require 424 s.in_range(1, bit_count - 1) 425 deferred 426 end 427 428 bit_rotate (s: INTEGER_8): like Current 429 -- Rotate by `s' positions (positive `s' shifts right, negative left 430 -- 431 -- See also `bit_rotate_right' and `bit_rotate_left'. 432 require 433 s.in_range(- (bit_count - 1), bit_count - 1) 434 deferred 435 end 436 437 prefix "~", bit_not: like Current 438 -- One's complement of `Current'. 439 deferred 440 end 441 442 infix "&", bit_and (other: like Current): like Current 443 -- Bitwise logical and of `Current' with `other'. 444 deferred 445 end 446 447 infix "|", bit_or (other: like Current): like Current 448 -- Bitwise logical inclusive or of `Current' with `other'. 449 deferred 450 end 451 452 bit_xor (other: like Current): like Current 453 -- Bitwise logical exclusive or of `Current' with `other'. 454 deferred 455 end 456 457 bit_shift (s: INTEGER_8): like Current 458 -- Shift by `s' positions (positive `s' shifts right (sign bit 459 -- copied), negative shifts left bits falling off the end are lost). 460 -- 461 -- See also infix "|>>" and infix "|<<". 462 require 463 s /= 0 464 deferred 465 end 466 467 bit_shift_unsigned (s: INTEGER_8): like Current 468 -- Shift by `s' positions (positive `s' shifts right (sign bit not 469 -- copied), negative left bits falling off the end are lost). 470 -- 471 -- See also infix "|>>>" and infix "|<<". 472 require 473 s /= 0 474 deferred 475 end 476 477feature {ANY} -- Miscellaneous: 478 sign: INTEGER_8 479 -- Sign of `Current' (0 or -1 or 1). 480 deferred 481 end 482 483 divisible (other: like Current): BOOLEAN 484 deferred 485 ensure 486 definition: Result = (other /= zero) 487 end 488 489 is_a_power_of_2: BOOLEAN 490 -- Is `Current' a power of 2? 491 require 492 Current > zero 493 deferred 494 end 495 496feature {ANY} -- Modular arithmetic (these wrap around on overflow) 497 infix "#+" (other: like Current): like Current 498 deferred 499 end 500 501 prefix "#-": like Current 502 deferred 503 end 504 505 infix "#-" (other: like Current): like Current 506 deferred 507 end 508 509 infix "#*" (other: like Current): like Current 510 deferred 511 end 512 513 infix "#//" (other: like Current): like Current 514 -- Integer division of `Current' by `other'. 515 -- 516 -- According to the ANSI C99: if `Current' and `other' are both non-negative, the `Result' is the 517 -- quotient of the Euclidian division; but this is not the general case, the `Result' value is the 518 -- algebraic quotient `Current/other' with any fractional part discarded. (This is often called 519 -- "truncated toward zero"). So, the corresponding remainder value only verifies the expression 520 -- `remainder.abs < other.abs'. 521 -- 522 -- See also infix "//", infix "#\\". 523 require 524 other /= zero 525 deferred 526 ensure 527 Result * other + Current #\\ other = Current 528 ansi_c_remainder: (other |<< 1 /= zero) implies (Current - Result * other).abs < other.abs 529 ansi_c_good_case: Current >= zero and other > zero implies Current - Result * other >= zero 530 end 531 532 infix "#\\" (other: like Current): like Current 533 -- Remainder of the integer division of `Current' by `other'. 534 -- According to the ANSI C99: 535 -- * if `Current' and `other' are both non-negative, 536 -- the `Result' is the remainder of the Euclidian division. 537 -- * but this is not the general case, 538 -- `Result' as the same sign as `Current' and only verify 539 -- the expression `Result.abs < other.abs'. 540 -- 541 -- See also infix "\\", infix "#//". 542 require 543 other /= zero 544 deferred 545 ensure 546 (Current - Result) #\\ other = zero 547 ansi_c_remainder: (other |<< 1 /= zero) implies Result.abs < other.abs 548 ansi_c_good_case: (Current >= zero and other > zero) implies Result >= zero 549 end 550 551feature {} 552 bit_count: INTEGER_8 553 -- Well, it is 8 for INTEGER_8, 16 for INTEGER_16 and so on. 554 -- Note that this feature is not exported because this information is part of the type. 555 -- This is actually used only for assertion here, in INTEGER_GENERAL. 556 deferred 557 ensure 558 Result = (object_size * 8) 559 end 560 561end -- class INTEGRAL 562-- 563-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file. 564-- 565-- Permission is hereby granted, free of charge, to any person obtaining a copy 566-- of this software and associated documentation files (the "Software"), to deal 567-- in the Software without restriction, including without limitation the rights 568-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 569-- copies of the Software, and to permit persons to whom the Software is 570-- furnished to do so, subject to the following conditions: 571-- 572-- The above copyright notice and this permission notice shall be included in 573-- all copies or substantial portions of the Software. 574-- 575-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 576-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 577-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 578-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 579-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 580-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 581-- THE SOFTWARE.