Commit 4038927f79469363e7f05e17e7eb42c6d6307412
1 parent
fcdefa65
Added a library file for handling big relative integers.
Showing
2 changed files
with
366 additions
and
6 deletions
Show diff stats
| 1 | + | ||
| 2 | + | ||
| 3 | + The Anubis Project | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + The type 'Int' of big relative integers and related tools. | ||
| 7 | + | ||
| 8 | + | ||
| 9 | + Author: Alain Proute' | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + The type of big relative integers. | ||
| 14 | + | ||
| 15 | +public type Int: | ||
| 16 | + positive(Nat abs), | ||
| 17 | + negative(Nat abs). | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + Because 'positive(0)' and 'negative(0)' must be the same number, we introduce a | ||
| 21 | + 'normalization' function: | ||
| 22 | + | ||
| 23 | +public define Int normalize(Int x). | ||
| 24 | + | ||
| 25 | + which returns 'x', except if 'x' is 'negative(0)', in which case it returns | ||
| 26 | + 'positive(0)'. | ||
| 27 | + | ||
| 28 | + All the operations below return normalized integers. If you define new operations | ||
| 29 | + returning integers, it is better that they return always normalized integers. | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + You may construct relative integers from natural integers. Just add a '+' or '-' sign | ||
| 33 | + in front of the natural. | ||
| 34 | + | ||
| 35 | +public define Int + Nat n. | ||
| 36 | +public define Int - Nat n. | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + A relative integer has an opposite and an absolute value. The absolute value may be | ||
| 41 | + interpreted either as a relative integers or as a natural integer. | ||
| 42 | + | ||
| 43 | +public define Int - Int x. | ||
| 44 | +public define Int abs(Int x). | ||
| 45 | + | ||
| 46 | + abs(Int x) as a 'Nat' is already defined as an implicit destructor in the definition of | ||
| 47 | + type 'Int'. | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + Comparisons. | ||
| 51 | + | ||
| 52 | +public define Bool Int x < Int y. | ||
| 53 | +public define Bool Int x =< Int y. | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + Arithmetic operations on relative integers. | ||
| 57 | + | ||
| 58 | +public define Int Int x + Int y. Addition. | ||
| 59 | +public define Int Int x - Int y. Substraction. | ||
| 60 | +public define Int Int x * Int y. Multiplication. | ||
| 61 | +public define Maybe((Int,Int)) Int x / Int y. Euclidian division. | ||
| 62 | + | ||
| 63 | + Of course, division by '0' is meaningless, hence the 'Maybe'. The pair of integers | ||
| 64 | + returned by the euclidian division is (quotient,remainder) in this order. The remainder | ||
| 65 | + is always positive, even if the dividend 'x' is negative. The remainder is always | ||
| 66 | + strictly smaller than the absolute value of the divisor 'y'. In other words, if the | ||
| 67 | + result is '(q,r)', we have: | ||
| 68 | + | ||
| 69 | + x = q*y + r | ||
| 70 | + 0 =< r < |y| | ||
| 71 | + | ||
| 72 | + | ||
| 73 | +public define (Int,Int,Int) bezout(Int x, Int y). gcd and Bezout coefficients. | ||
| 74 | + | ||
| 75 | + This function returns a triplet '(d,u,v)', where 'd' is the gcd (greatest common | ||
| 76 | + divisor) of 'x' and 'y', 'u' and 'v' a pair of Bezout coefficients. In other words, it | ||
| 77 | + gives the gcd as a linear combinaison of 'x' and 'y': | ||
| 78 | + | ||
| 79 | + d = u*x + v*y | ||
| 80 | + | ||
| 81 | + According to the interpretation of this formula in terms of ideals in a principal ring, | ||
| 82 | + we have: | ||
| 83 | + | ||
| 84 | + bezout(0,0) = (0,1,1) | ||
| 85 | + bezout(x,0) = (x,1,1) if x /= 0 | ||
| 86 | + bezout(0,y) = (y,1,1) if y /= 0 | ||
| 87 | + | ||
| 88 | + | ||
| 89 | + We also have: | ||
| 90 | + | ||
| 91 | +public define Int gcd(Int x, Int y). The gcd alone. | ||
| 92 | +public define Int lcm(Int x, Int y). The lcm (least common multiple). | ||
| 93 | + | ||
| 94 | + Again, we have: | ||
| 95 | + | ||
| 96 | + gcd(0,0) = 0 | ||
| 97 | + gcd(x,0) = x if x /= 0 | ||
| 98 | + gcd(0,y) = y if y /= 0 | ||
| 99 | + | ||
| 100 | + lcm(0,0) = 0 | ||
| 101 | + lcm(x,0) = 0 if x /= 0 | ||
| 102 | + lcm(0,y) = 0 if y /= 0 | ||
| 103 | + | ||
| 104 | + Notice that the divisibility relation 'x divides y' turns 'Int' into a preordered set, | ||
| 105 | + hence into a category. In this category, '0' is the final object, and an object is | ||
| 106 | + initial if and only if it is an invertible element (in the case of Int, the invertibles | ||
| 107 | + are '+1' and '-1'). The gcd is the infimum (the categorical product) with respect to | ||
| 108 | + the divisibility relation and the lcm is the supremum (the categorical sum) with | ||
| 109 | + respect to the divisibility relation. The above special cases are coherent with this | ||
| 110 | + interpretation. | ||
| 111 | + | ||
| 112 | + | ||
| 113 | + | ||
| 114 | + --- That's all for the public part ! -------------------------------------------------- | ||
| 115 | + | ||
| 116 | + | ||
| 117 | +define Int normalize(Int x) = | ||
| 118 | + if x is | ||
| 119 | + { | ||
| 120 | + positive(n) then x, | ||
| 121 | + negative(n) then | ||
| 122 | + if n = 0 | ||
| 123 | + then positive(0) | ||
| 124 | + else x | ||
| 125 | + }. | ||
| 126 | + | ||
| 127 | + | ||
| 128 | +public define Int + Nat n = positive(n). | ||
| 129 | +public define Int - Nat n = if n = 0 then positive(0) else negative(n). | ||
| 130 | + | ||
| 131 | + | ||
| 132 | +public define Int | ||
| 133 | + - Int x | ||
| 134 | + = | ||
| 135 | + if x is | ||
| 136 | + { | ||
| 137 | + positive(n) then if n = 0 then positive(0) else negative(n), | ||
| 138 | + negative(n) then positive(n) | ||
| 139 | + }. | ||
| 140 | + | ||
| 141 | + | ||
| 142 | +public define Int | ||
| 143 | + abs | ||
| 144 | + ( | ||
| 145 | + Int x | ||
| 146 | + ) = | ||
| 147 | + if x is | ||
| 148 | + { | ||
| 149 | + positive(n) then x, | ||
| 150 | + negative(n) then positive(n) | ||
| 151 | + }. | ||
| 152 | + | ||
| 153 | + | ||
| 154 | +public define Bool | ||
| 155 | + Int x < Int y | ||
| 156 | + = | ||
| 157 | + if x is | ||
| 158 | + { | ||
| 159 | + positive(n) then if y is | ||
| 160 | + { | ||
| 161 | + positive(m) then n < m, | ||
| 162 | + negative(m) then false | ||
| 163 | + }, | ||
| 164 | + negative(n) then if y is | ||
| 165 | + { | ||
| 166 | + positive(m) then if n = 0 | ||
| 167 | + then if m = 0 | ||
| 168 | + then false | ||
| 169 | + else true | ||
| 170 | + else true | ||
| 171 | + negative(m) then m < n | ||
| 172 | + } | ||
| 173 | + }. | ||
| 174 | + | ||
| 175 | + | ||
| 176 | +public define Bool | ||
| 177 | + Int x =< Int y | ||
| 178 | + = | ||
| 179 | + if x is | ||
| 180 | + { | ||
| 181 | + positive(n) then if y is | ||
| 182 | + { | ||
| 183 | + positive(m) then n =< m, | ||
| 184 | + negative(m) then if n = 0 | ||
| 185 | + then if m = 0 | ||
| 186 | + then true // 0 =< 0 | ||
| 187 | + else false // x = 0 and y < 0 | ||
| 188 | + else false // x > 0 and y =< 0 | ||
| 189 | + }, | ||
| 190 | + negative(n) then if y is | ||
| 191 | + { | ||
| 192 | + positive(m) then true | ||
| 193 | + negative(m) then m =< n | ||
| 194 | + } | ||
| 195 | + }. | ||
| 196 | + | ||
| 197 | + | ||
| 198 | + | ||
| 199 | + | ||
| 200 | + | ||
| 201 | +public define Int | ||
| 202 | + Int x + Int y | ||
| 203 | + = | ||
| 204 | + if x is | ||
| 205 | + { | ||
| 206 | + positive(n) then if y is | ||
| 207 | + { | ||
| 208 | + positive(m) then positive(n+m), | ||
| 209 | + negative(m) then if n >= m | ||
| 210 | + then positive(n |-| m) | ||
| 211 | + else negative(m |-| n) | ||
| 212 | + }, | ||
| 213 | + negative(n) then if y is | ||
| 214 | + { | ||
| 215 | + positive(m) then if n > m | ||
| 216 | + then negative(n |-| m) | ||
| 217 | + else positive(m |-| n), | ||
| 218 | + negative(m) then negative(n+m) | ||
| 219 | + } | ||
| 220 | + }. | ||
| 221 | + | ||
| 222 | + | ||
| 223 | + | ||
| 224 | +public define Int | ||
| 225 | + Int x - Int y | ||
| 226 | + = | ||
| 227 | + x + -y. | ||
| 228 | + | ||
| 229 | + | ||
| 230 | + | ||
| 231 | +public define Int | ||
| 232 | + Int x * Int y | ||
| 233 | + = | ||
| 234 | + if x is | ||
| 235 | + { | ||
| 236 | + positive(n) then if y is | ||
| 237 | + { | ||
| 238 | + positive(m) then positive(n*m), | ||
| 239 | + negative(m) then normalize(negative(n*m)) | ||
| 240 | + }, | ||
| 241 | + negative(n) then if y is | ||
| 242 | + { | ||
| 243 | + positive(m) then normalize(negative(n*m)), | ||
| 244 | + negative(m) then positive(n*m) | ||
| 245 | + } | ||
| 246 | + }. | ||
| 247 | + | ||
| 248 | + | ||
| 249 | + | ||
| 250 | + | ||
| 251 | + The euclidian division for type 'Int'. | ||
| 252 | + | ||
| 253 | +public define Maybe((Int,Int)) | ||
| 254 | + Int x / Int y | ||
| 255 | + = | ||
| 256 | + if ((:Nat)abs(x)) / ((:Nat)abs(y)) is | ||
| 257 | + { | ||
| 258 | + failure then failure, | ||
| 259 | + success(p) then if p is (Nat q, Nat r) then | ||
| 260 | + if x is | ||
| 261 | + { | ||
| 262 | + positive(n) then if y is | ||
| 263 | + { | ||
| 264 | + positive(m) then | ||
| 265 | + success((positive(q),positive(r))), | ||
| 266 | + | ||
| 267 | + negative(m) then // x = q*(-y) + r = (-q)*y + r | ||
| 268 | + success((normalize(negative(q)),positive(r))) | ||
| 269 | + }, | ||
| 270 | + negative(n) then if y is | ||
| 271 | + { | ||
| 272 | + positive(m) then if r = 0 | ||
| 273 | + then // -x = q*y hence x = (-q)*y + 0 | ||
| 274 | + success((normalize(negative(q)),positive(0))) | ||
| 275 | + else // -x = q*y + r hence x = (-q)*y - r = (-q-1)*y + (y-r) and 0 =< y-r < |y| | ||
| 276 | + success((negative(q+1),positive(m |-| r))), | ||
| 277 | + | ||
| 278 | + negative(m) then if r = 0 | ||
| 279 | + then // -x = q*(-y) hence x = q*y + 0 | ||
| 280 | + success((positive(q),positive(0))) | ||
| 281 | + else // -x = q*(-y) + r hence x = q*y - r = (q+1)*y + (-y-r) and 0 =< -y-r < |y| | ||
| 282 | + success((positive(q+1),positive(m |-| r))) | ||
| 283 | + } | ||
| 284 | + } | ||
| 285 | + }. | ||
| 286 | + | ||
| 287 | + | ||
| 288 | + | ||
| 289 | + | ||
| 290 | + | ||
| 291 | + gcd and Bezout coefficients for type 'Int'. | ||
| 292 | + | ||
| 293 | +public define (Int,Int,Int) | ||
| 294 | + bezout | ||
| 295 | + ( | ||
| 296 | + Int x, | ||
| 297 | + Int y | ||
| 298 | + ) = | ||
| 299 | + if abs(x) < (:Nat)abs(y) | ||
| 300 | + then (if bezout(y,x) is (d,u,v) then (d,v,u)) | ||
| 301 | + else | ||
| 302 | + // | ||
| 303 | + // Apply Euclid's algorithm. | ||
| 304 | + // | ||
| 305 | + if x/y is | ||
| 306 | + { | ||
| 307 | + failure then // 'y' is zero: finished | ||
| 308 | + (x,+1,+1), | ||
| 309 | + | ||
| 310 | + success(p) then if p is (q,r) then | ||
| 311 | + // | ||
| 312 | + // We have: | ||
| 313 | + // x =q*y + r and 0 =< r < |y| | ||
| 314 | + // | ||
| 315 | + if bezout(y,r) is (d,a,b) then | ||
| 316 | + // | ||
| 317 | + // we have the gcd, and: | ||
| 318 | + // | ||
| 319 | + // d = a*y + b*r | ||
| 320 | + // = a*y + b*(x - q*y) | ||
| 321 | + // = b*x + (a - b*q)*y | ||
| 322 | + // | ||
| 323 | + (d,b,a - b*q) | ||
| 324 | + }. | ||
| 325 | + | ||
| 326 | + | ||
| 327 | + gcd and lcm. | ||
| 328 | + | ||
| 329 | +public define Int | ||
| 330 | + gcd | ||
| 331 | + ( | ||
| 332 | + Int x, | ||
| 333 | + Int y | ||
| 334 | + ) = | ||
| 335 | + if bezout(x,y) is (d,_,_) then d. | ||
| 336 | + | ||
| 337 | + | ||
| 338 | +public define Int | ||
| 339 | + lcm | ||
| 340 | + ( | ||
| 341 | + Int x, | ||
| 342 | + Int y | ||
| 343 | + ) = | ||
| 344 | + if bezout(x,y) is (d,_,_) then | ||
| 345 | + if x/d is | ||
| 346 | + { | ||
| 347 | + failure then // 'x' and 'y' are zero | ||
| 348 | + +0, | ||
| 349 | + | ||
| 350 | + success(p) then if p is (q,r) then // actually r is zero | ||
| 351 | + q*y | ||
| 352 | + }. | ||
| 353 | + | ||
| 354 | + | ||
| 355 | + | ||
| 356 | + | ||
| 357 | + | ||
| 0 | \ No newline at end of file | 358 | \ No newline at end of file |
anubis_dev/library/predefined.anubis
| @@ -2826,14 +2826,17 @@ public define ByteArray sha1($T d) = £sha1(serialize(d)). | @@ -2826,14 +2826,17 @@ public define ByteArray sha1($T d) = £sha1(serialize(d)). | ||
| 2826 | usual ones (as available for example under UNIX) when 'd' is a byte array. When 'd' is | 2826 | usual ones (as available for example under UNIX) when 'd' is a byte array. When 'd' is |
| 2827 | not a byte array, 'd' is first serialized before the usual algorithm is applied to it. | 2827 | not a byte array, 'd' is first serialized before the usual algorithm is applied to it. |
| 2828 | 2828 | ||
| 2829 | - Note: at the time of writting, only sha1 is implemented for both Linux and Windows. | ||
| 2830 | - | ||
| 2831 | - | ||
| 2832 | - | ||
| 2833 | - | 2829 | + So, be carefull with strings. If you use one of these functions on a character string, |
| 2830 | + it will not give the standard result. In order to get the standard result, convert your | ||
| 2831 | + string into a byte array first, like this: | ||
| 2832 | + | ||
| 2833 | + sha1(to_byte_array("....")) | ||
| 2834 | + | ||
| 2835 | + | ||
| 2836 | + | ||
| 2837 | + | ||
| 2834 | 2838 | ||
| 2835 | 2839 | ||
| 2836 | - | ||
| 2837 | *** (9.2) Symmetric cryptography ('blowfish_encrypt', 'blowfish_decrypt'). | 2840 | *** (9.2) Symmetric cryptography ('blowfish_encrypt', 'blowfish_decrypt'). |
| 2838 | 2841 | ||
| 2839 | The 'Blowfish' algorithm is a block cipher designed by Bruce Schneier (see his book: | 2842 | The 'Blowfish' algorithm is a block cipher designed by Bruce Schneier (see his book: |