| 1 | (******************************************************************************* |
|---|
| 2 | Copyright 2008 Sun Microsystems, Inc., |
|---|
| 3 | 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
|---|
| 4 | All rights reserved. |
|---|
| 5 | |
|---|
| 6 | U.S. Government Rights - Commercial software. |
|---|
| 7 | Government users are subject to the Sun Microsystems, Inc. standard |
|---|
| 8 | license agreement and applicable provisions of the FAR and its supplements. |
|---|
| 9 | |
|---|
| 10 | Use is subject to license terms. |
|---|
| 11 | |
|---|
| 12 | This distribution may include materials developed by third parties. |
|---|
| 13 | |
|---|
| 14 | Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered |
|---|
| 15 | trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|---|
| 16 | ******************************************************************************) |
|---|
| 17 | |
|---|
| 18 | component FortressLibrary |
|---|
| 19 | import NativeArray.{...} |
|---|
| 20 | import NatReflect.{...} |
|---|
| 21 | import JavaString.{...} |
|---|
| 22 | import List.{AnyList} |
|---|
| 23 | |
|---|
| 24 | export FortressLibrary |
|---|
| 25 | |
|---|
| 26 | (************************************************************ |
|---|
| 27 | * Simple Combinators |
|---|
| 28 | ************************************************************) |
|---|
| 29 | |
|---|
| 30 | (** Casting *) |
|---|
| 31 | |
|---|
| 32 | cast[\T extends Any\](x:Any):T = |
|---|
| 33 | typecase x of |
|---|
| 34 | T => x |
|---|
| 35 | else => throw CastError |
|---|
| 36 | end |
|---|
| 37 | |
|---|
| 38 | instanceOf[\T extends Any\](x:Any):Boolean = |
|---|
| 39 | typecase x of |
|---|
| 40 | T => true |
|---|
| 41 | else => false |
|---|
| 42 | end |
|---|
| 43 | |
|---|
| 44 | (** Useful functions *) |
|---|
| 45 | |
|---|
| 46 | ignore(_:Any):() = () |
|---|
| 47 | |
|---|
| 48 | identity[\T extends Any\](x:T):T = x |
|---|
| 49 | |
|---|
| 50 | (* Should we depracate tuple and use identity instead? Decision: no. *) |
|---|
| 51 | tuple[\T\](x:T):T = x |
|---|
| 52 | |
|---|
| 53 | (* Function composition *) |
|---|
| 54 | opr COMPOSE[\A,B,C\](f: B->C, g: A->B): A->C = fn (a:A): C => f(g(a)) |
|---|
| 55 | |
|---|
| 56 | (** Reflection of static type parameters for overloading purposes. |
|---|
| 57 | Works around shortcomings in the story on parametric overloading |
|---|
| 58 | (all overloadings must have the same parameters with the same |
|---|
| 59 | bounds). Allows us to overload a function based on the parametric |
|---|
| 60 | type of an output. *) |
|---|
| 61 | |
|---|
| 62 | object __Proxy[\T extends (* U *) Any\] |
|---|
| 63 | (* extends { __Proxy[\U\], Object } where { U extends Any } *) |
|---|
| 64 | getter toString() = "__Proxy object, should not be user-visible." |
|---|
| 65 | end |
|---|
| 66 | |
|---|
| 67 | fail[\T\](s:String):T = do |
|---|
| 68 | println("FAIL: " s) |
|---|
| 69 | (* throwError(s) *) |
|---|
| 70 | throw FailCalled(s) |
|---|
| 71 | end |
|---|
| 72 | |
|---|
| 73 | (************************************************************ |
|---|
| 74 | * Control over locality and location |
|---|
| 75 | ************************************************************) |
|---|
| 76 | |
|---|
| 77 | (* At the moment all Fortress objects are immediately shared by default. *) |
|---|
| 78 | |
|---|
| 79 | shared[\T extends Any\](x:T): T = x |
|---|
| 80 | |
|---|
| 81 | isShared(x:Any): Boolean = true |
|---|
| 82 | |
|---|
| 83 | localize[\T extends Any\](x:T): T = x |
|---|
| 84 | |
|---|
| 85 | (* copy is presently unimplemented. |
|---|
| 86 | copy[\T extends Any\](x:T): T = |
|---|
| 87 | *) |
|---|
| 88 | |
|---|
| 89 | trait Region extends Equality[\Region\] |
|---|
| 90 | getter toString(): String |
|---|
| 91 | isLocalTo(r: Region): Boolean = false |
|---|
| 92 | opr =(self, other:Region): Boolean = self SEQV other |
|---|
| 93 | end |
|---|
| 94 | |
|---|
| 95 | object Global extends Region |
|---|
| 96 | getter toString(): String = "Global" |
|---|
| 97 | isLocalTo(_: Region): Boolean = true |
|---|
| 98 | end |
|---|
| 99 | |
|---|
| 100 | region(a:Any): Region = Global |
|---|
| 101 | |
|---|
| 102 | here(): Region = Global |
|---|
| 103 | |
|---|
| 104 | (************************************************************ |
|---|
| 105 | * Equality and ordering |
|---|
| 106 | ************************************************************) |
|---|
| 107 | |
|---|
| 108 | opr =(a:Any, b:Any):Boolean = a SEQV b |
|---|
| 109 | |
|---|
| 110 | opr =/=(a:Any, b:Any):Boolean = NOT (a=b) |
|---|
| 111 | |
|---|
| 112 | trait Equality[\Self extends Equality[\Self\]\] |
|---|
| 113 | opr =(self, other:Self): Boolean |
|---|
| 114 | end |
|---|
| 115 | |
|---|
| 116 | (** Total ordering *) |
|---|
| 117 | |
|---|
| 118 | object LexicographicPartialReduction |
|---|
| 119 | extends { MonoidReduction[\Comparison\], |
|---|
| 120 | ReductionWithZeroes[\Comparison, Comparison\] } |
|---|
| 121 | getter toString():String = "Lexicographic reduction on partial order" |
|---|
| 122 | empty(): Comparison = EqualTo |
|---|
| 123 | join(a:Comparison, b:Comparison):Comparison = a LEXICO b |
|---|
| 124 | isZero(_:Unordered): Boolean = true |
|---|
| 125 | isZero(_:Comparison): Boolean = false |
|---|
| 126 | end |
|---|
| 127 | |
|---|
| 128 | object LexicographicReduction |
|---|
| 129 | extends { MonoidReduction[\TotalComparison\], |
|---|
| 130 | ReductionWithZeroes[\TotalComparison, TotalComparison\] } |
|---|
| 131 | getter toString():String = "Lexicographic reduction on total order" |
|---|
| 132 | empty(): TotalComparison = EqualTo |
|---|
| 133 | join(a:TotalComparison, b:TotalComparison):TotalComparison = a LEXICO b |
|---|
| 134 | isLeftZero(_:EqualTo): Boolean = false |
|---|
| 135 | isLeftZero(_:Comparison): Boolean = true |
|---|
| 136 | end |
|---|
| 137 | |
|---|
| 138 | opr BIG LEXICO(): BigReduction[\TotalComparison, TotalComparison\] = |
|---|
| 139 | BigReduction[\TotalComparison,TotalComparison\](LexicographicReduction) |
|---|
| 140 | |
|---|
| 141 | |
|---|
| 142 | trait Comparison |
|---|
| 143 | extends { StandardPartialOrder[\Comparison\] } |
|---|
| 144 | comprises { Unordered, TotalComparison } |
|---|
| 145 | getter toString(): String |
|---|
| 146 | opr =(self, other:Comparison): Boolean = false |
|---|
| 147 | opr LEXICO(self, other:Comparison): Comparison = Unordered |
|---|
| 148 | opr INVERSE(self): Comparison |
|---|
| 149 | end |
|---|
| 150 | |
|---|
| 151 | (** Unordered is the outcome of a CMP b when a and b are partially |
|---|
| 152 | ordered and no ordering relationship exists between them. **) |
|---|
| 153 | object Unordered extends Comparison |
|---|
| 154 | getter toString(): String = "Unordered" |
|---|
| 155 | opr =(self, other:Unordered): Boolean = true |
|---|
| 156 | opr <(self, other:Comparison): Boolean = false |
|---|
| 157 | opr INVERSE(self): Comparison = Unordered |
|---|
| 158 | end |
|---|
| 159 | |
|---|
| 160 | trait TotalComparison |
|---|
| 161 | extends { Comparison, StandardTotalOrder[\TotalComparison\] } |
|---|
| 162 | comprises { LessThan, EqualTo, GreaterThan } |
|---|
| 163 | (* We're both a partial order (including Unordered) and a total |
|---|
| 164 | order (TotalComparison alone). Avoid ambiguity between the |
|---|
| 165 | default definitions of CMP and >=. *) |
|---|
| 166 | opr =(self, other:TotalComparison): Boolean = false |
|---|
| 167 | opr =(self, other:Unordered): Boolean = false |
|---|
| 168 | opr CMP(self, other:Unordered): Comparison = Unordered |
|---|
| 169 | opr <(self, other:Unordered): Boolean = false |
|---|
| 170 | opr >=(self, other:Unordered): Boolean = false |
|---|
| 171 | opr >=(self, other:Comparison): Boolean = NOT (other < self) |
|---|
| 172 | opr LEXICO(self, other:TotalComparison): TotalComparison = self |
|---|
| 173 | opr LEXICO(self, other:()->TotalComparison): TotalComparison = self |
|---|
| 174 | opr INVERSE(self): TotalComparison |
|---|
| 175 | end |
|---|
| 176 | |
|---|
| 177 | object LessThan extends TotalComparison |
|---|
| 178 | getter toString(): String = "LessThan" |
|---|
| 179 | opr =(self, other:LessThan): Boolean = true |
|---|
| 180 | opr CMP(self, other:LessThan): TotalComparison = EqualTo |
|---|
| 181 | opr CMP(self, other:TotalComparison): TotalComparison = GreaterThan |
|---|
| 182 | opr <(self, other:LessThan): Boolean = false |
|---|
| 183 | opr <(self, other:TotalComparison): Boolean = true |
|---|
| 184 | opr INVERSE(self): TotalComparison = GreaterThan |
|---|
| 185 | end |
|---|
| 186 | |
|---|
| 187 | object GreaterThan extends TotalComparison |
|---|
| 188 | getter toString(): String = "GreaterThan" |
|---|
| 189 | opr =(self, other:GreaterThan): Boolean = true |
|---|
| 190 | opr CMP(self, other:GreaterThan): TotalComparison = EqualTo |
|---|
| 191 | opr CMP(self, other:TotalComparison): TotalComparison = LessThan |
|---|
| 192 | opr <(self, other:TotalComparison): Boolean = false |
|---|
| 193 | opr INVERSE(self): TotalComparison = LessThan |
|---|
| 194 | end |
|---|
| 195 | |
|---|
| 196 | object EqualTo extends TotalComparison |
|---|
| 197 | getter toString(): String = "EqualTo" |
|---|
| 198 | opr =(self, other:EqualTo): Boolean = true |
|---|
| 199 | opr CMP(self, other:TotalComparison): TotalComparison = INVERSE other |
|---|
| 200 | opr <(self, other:GreaterThan): Boolean = true |
|---|
| 201 | opr <(self, other:TotalComparison): Boolean = false |
|---|
| 202 | opr LEXICO(self, other:TotalComparison): TotalComparison = other |
|---|
| 203 | opr LEXICO(self, other:()->TotalComparison): TotalComparison = other() |
|---|
| 204 | opr INVERSE(self): TotalComparison = EqualTo |
|---|
| 205 | end |
|---|
| 206 | |
|---|
| 207 | (** StandardPartialOrder is partial ordering using <,>,<=,>=,=, and CMP. |
|---|
| 208 | This is primarily for floating-point values. Minimal complete |
|---|
| 209 | definition: CMP or { <, = }. **) |
|---|
| 210 | trait StandardPartialOrder[\Self extends StandardPartialOrder[\Self\]\] |
|---|
| 211 | extends { Equality[\Self\] } |
|---|
| 212 | opr CMP(self, other:Self): Comparison = |
|---|
| 213 | if self < other then LessThan |
|---|
| 214 | elif other > self then GreaterThan |
|---|
| 215 | elif self = other then EqualTo |
|---|
| 216 | else Unordered |
|---|
| 217 | end |
|---|
| 218 | opr <(self, other:Self): Boolean = LessThan = (self CMP other) |
|---|
| 219 | opr >(self, other:Self): Boolean = other < self |
|---|
| 220 | opr =(self, other:Self): Boolean = EqualTo = (self CMP other) |
|---|
| 221 | opr <=(self, other:Self): Boolean = other >= self |
|---|
| 222 | opr >=(self, other:Self): Boolean = (self = other OR: self > other) |
|---|
| 223 | end |
|---|
| 224 | |
|---|
| 225 | (** %StandardMin% is a MIN operator; most types that implement %MIN% |
|---|
| 226 | will implement a corresponding total order. It's a separate type |
|---|
| 227 | to account for the existence of floating point numbers, for which |
|---|
| 228 | NaN counts as a bottom that is less than anything else but doesn't |
|---|
| 229 | actually participate in the standard total ordering. It is |
|---|
| 230 | otherwise the case that %a MIN b = a% when %a <= b% and that |
|---|
| 231 | %a MIN b = b MIN a%. **) |
|---|
| 232 | trait StandardMin[\T extends StandardMin[\T\]\] |
|---|
| 233 | opr MIN(self, other:T): T |
|---|
| 234 | end |
|---|
| 235 | |
|---|
| 236 | (** %StandardMax% is a MAX operator; most types that implement %MAX% |
|---|
| 237 | will implement a corresponding total order. It's a separate type |
|---|
| 238 | to account for the existence of floating point numbers, for which |
|---|
| 239 | NaN counts as a bottom that is less than anything else but doesn't |
|---|
| 240 | actually participate in the standard total ordering. It is |
|---|
| 241 | otherwise the case that %a MAX b = a% when %a <= b% and that |
|---|
| 242 | %a MAX b = b MAX a%. **) |
|---|
| 243 | trait StandardMax[\T extends StandardMax[\T\]\] |
|---|
| 244 | opr MAX(self, other:T): T |
|---|
| 245 | end |
|---|
| 246 | |
|---|
| 247 | (** StandardTotalOrder is the usual total order using <,>,<=,>=,=, and |
|---|
| 248 | CMP. Most values that define a comparison should do so using |
|---|
| 249 | this. Minimal complete definition: either CMP or < (it's |
|---|
| 250 | advisable to define = in the latter case). As noted above, %MIN% |
|---|
| 251 | and %MAX% respect the total order and are defined in the obvious |
|---|
| 252 | way. **) |
|---|
| 253 | trait StandardTotalOrder[\Self extends StandardTotalOrder[\Self\]\] |
|---|
| 254 | extends { StandardPartialOrder[\Self\], StandardMin[\Self\], StandardMax[\Self\] } |
|---|
| 255 | opr CMP(self, other:Self): TotalComparison = |
|---|
| 256 | if self < other then LessThan |
|---|
| 257 | elif other < self then GreaterThan |
|---|
| 258 | else EqualTo |
|---|
| 259 | end |
|---|
| 260 | opr >=(self, other:Self): Boolean = NOT (self < other) |
|---|
| 261 | opr <=(self, other:Self): Boolean = NOT (other < self) |
|---|
| 262 | opr MIN(self, other:Self): Self = if other < self then other else self end |
|---|
| 263 | opr MAX(self, other:Self): Self = if self < other then other else self end |
|---|
| 264 | end |
|---|
| 265 | |
|---|
| 266 | (** Assertion *) |
|---|
| 267 | assert(flag:Boolean): () = |
|---|
| 268 | if NOT flag then |
|---|
| 269 | fail("Assertion failed!") |
|---|
| 270 | end |
|---|
| 271 | |
|---|
| 272 | assert(flag: Boolean, failMsg: String): () = |
|---|
| 273 | if NOT flag then |
|---|
| 274 | fail(failMsg) |
|---|
| 275 | end |
|---|
| 276 | |
|---|
| 277 | assert(x:Any, y:Any, failMsg: Any...): () = |
|---|
| 278 | if x =/= y then |
|---|
| 279 | msg = x " =/= " y "; " (BIG || failMsg) |
|---|
| 280 | fail(msg) |
|---|
| 281 | end |
|---|
| 282 | |
|---|
| 283 | deny(flag:Boolean): () = assert(NOT flag) |
|---|
| 284 | |
|---|
| 285 | deny(flag: Boolean, failMsg: String): () = assert(NOT flag, failMsg) |
|---|
| 286 | |
|---|
| 287 | deny(x:Any, y:Any, failMsg: Any...): () = |
|---|
| 288 | if x = y then |
|---|
| 289 | msg = x " = " y "; " (BIG || failMsg) |
|---|
| 290 | fail(msg) |
|---|
| 291 | end |
|---|
| 292 | |
|---|
| 293 | shouldRaise⟦Ex extends Exception⟧ (expr: ()→()): () = do |
|---|
| 294 | try |
|---|
| 295 | expr() |
|---|
| 296 | throw ForbiddenException |
|---|
| 297 | catch x |
|---|
| 298 | Ex => assert(true) (* This is what we hope for *) |
|---|
| 299 | forbid Exception |
|---|
| 300 | end |
|---|
| 301 | end |
|---|
| 302 | |
|---|
| 303 | |
|---|
| 304 | (************************************************************ |
|---|
| 305 | * Numeric hierarchy |
|---|
| 306 | ************************************************************) |
|---|
| 307 | |
|---|
| 308 | (** Additive group making use of +. Must define + and either unary or binary -. **) |
|---|
| 309 | trait AdditiveGroup[\Self extends AdditiveGroup[\Self\]\] |
|---|
| 310 | getter zero(): Self = self - self |
|---|
| 311 | opr +(self, other: Self): Self |
|---|
| 312 | opr -(self, other: Self): Self = self + (-other) |
|---|
| 313 | opr -(self) : Self = self.zero - self |
|---|
| 314 | end |
|---|
| 315 | |
|---|
| 316 | (** Place holder for exclusions of MultiplicativeRing **) |
|---|
| 317 | trait AnyMultiplicativeRing end |
|---|
| 318 | |
|---|
| 319 | (** Multiplicative ring using TIMES and juxtaposition. |
|---|
| 320 | Define opr TIMES; juxtaposition is defined in terms of TIMES. **) |
|---|
| 321 | trait MultiplicativeRing[\Self extends MultiplicativeRing[\Self\]\] |
|---|
| 322 | extends { AdditiveGroup[\Self\], AnyMultiplicativeRing } |
|---|
| 323 | getter one(): Self |
|---|
| 324 | opr TIMES(self, other:Self): Self |
|---|
| 325 | opr juxtaposition(self, other:Self): Self = self TIMES other |
|---|
| 326 | (** Exponentiation need only deal with natural exponents. **) |
|---|
| 327 | opr ^(self, other:AnyIntegral): Self |
|---|
| 328 | end |
|---|
| 329 | |
|---|
| 330 | (** The use of StandardTotalOrder here is a lie; it will have to suffice |
|---|
| 331 | until we can deal gracefully with NaNs disobeying the ordering rules |
|---|
| 332 | (and even the equivalence rules for = and =/=). **) |
|---|
| 333 | trait Number |
|---|
| 334 | extends { StandardPartialOrder[\Number\], StandardMin[\Number\], StandardMax[\Number\], |
|---|
| 335 | AdditiveGroup[\Number\], MultiplicativeRing[\Number\] } |
|---|
| 336 | comprises { RR64 } |
|---|
| 337 | getter zero(): Number = 0.0 |
|---|
| 338 | getter one(): Number = 1.0 |
|---|
| 339 | getter toString(): String |
|---|
| 340 | opr |self| : Number = |
|---|
| 341 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Abs") |
|---|
| 342 | opr =(self, b:Number):Boolean = |
|---|
| 343 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Eq") |
|---|
| 344 | opr =/=(self, b:Number):Boolean = |
|---|
| 345 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NEq") |
|---|
| 346 | opr <(self, b:Number):Boolean = |
|---|
| 347 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Less") |
|---|
| 348 | opr <=(self, b:Number):Boolean = |
|---|
| 349 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$LessEq") |
|---|
| 350 | opr >(self, b:Number):Boolean = |
|---|
| 351 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Greater") |
|---|
| 352 | opr >=(self, b:Number):Boolean = |
|---|
| 353 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$GreaterEq") |
|---|
| 354 | opr CMP(self, b:Number):Comparison = |
|---|
| 355 | if self<b then LessThan |
|---|
| 356 | elif self>b then GreaterThan |
|---|
| 357 | elif self=b then EqualTo |
|---|
| 358 | else Unordered |
|---|
| 359 | end |
|---|
| 360 | (** In case of NaN, %MIN% and %MAX% return a NaN, otherwise it respects the |
|---|
| 361 | total order. **) |
|---|
| 362 | opr MIN(self, b:Number):Number = |
|---|
| 363 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Min") |
|---|
| 364 | opr MAX(self, b:Number):Number = |
|---|
| 365 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Max") |
|---|
| 366 | |
|---|
| 367 | opr -(self):RR64 = |
|---|
| 368 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Negate") |
|---|
| 369 | opr +(self,b:Number):RR64 = |
|---|
| 370 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Add") |
|---|
| 371 | opr -(self,b:Number):RR64 = |
|---|
| 372 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sub") |
|---|
| 373 | opr DOT(self,b:Number):RR64 = |
|---|
| 374 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul") |
|---|
| 375 | opr TIMES(self,b:Number):RR64 = |
|---|
| 376 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul") |
|---|
| 377 | opr juxtaposition |
|---|
| 378 | (self,b:Number):RR64 = |
|---|
| 379 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul") |
|---|
| 380 | opr /(self,b:Number):RR64 = |
|---|
| 381 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Div") |
|---|
| 382 | opr SQRT(self):RR64 = |
|---|
| 383 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sqrt") |
|---|
| 384 | opr PLUS_UP(self,b:Number):RR64 = |
|---|
| 385 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddUpNoNaN") |
|---|
| 386 | opr MINUS_UP(self,b:Number):RR64 = |
|---|
| 387 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubUpNoNaN") |
|---|
| 388 | opr DOT_UP(self,b:Number):RR64 = |
|---|
| 389 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulUpNoNaN") |
|---|
| 390 | opr SLASH_UP(self,b:Number):RR64 = |
|---|
| 391 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivUpNoNaN") |
|---|
| 392 | opr SQRT_UP(self):RR64 = |
|---|
| 393 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SqrtUp") |
|---|
| 394 | opr PLUS_DOWN(self,b:Number):RR64 = |
|---|
| 395 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddDownNoNaN") |
|---|
| 396 | opr MINUS_DOWN(self,b:Number):RR64 = |
|---|
| 397 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubDownNoNaN") |
|---|
| 398 | opr DOT_DOWN(self,b:Number):RR64 = |
|---|
| 399 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulDownNoNaN") |
|---|
| 400 | opr SLASH_DOWN(self,b:Number):RR64 = |
|---|
| 401 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivDownNoNaN") |
|---|
| 402 | opr SQRT_DOWN(self):RR64 = |
|---|
| 403 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SqrtDown") |
|---|
| 404 | opr IEEE_PLUS_UP(self,b:Number):RR64 = |
|---|
| 405 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddUp") |
|---|
| 406 | opr IEEE_MINUS_UP(self,b:Number):RR64 = |
|---|
| 407 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubUp") |
|---|
| 408 | opr IEEE_DOT_UP(self,b:Number):RR64 = |
|---|
| 409 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulUp") |
|---|
| 410 | opr IEEE_SLASH_UP(self,b:Number):RR64 = |
|---|
| 411 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivUp") |
|---|
| 412 | opr IEEE_PLUS_DOWN(self,b:Number):RR64 = |
|---|
| 413 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddDown") |
|---|
| 414 | opr IEEE_MINUS_DOWN(self,b:Number):RR64 = |
|---|
| 415 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubDown") |
|---|
| 416 | opr IEEE_DOT_DOWN(self,b:Number):RR64 = |
|---|
| 417 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulDown") |
|---|
| 418 | opr IEEE_SLASH_DOWN(self,b:Number):RR64 = |
|---|
| 419 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivDown") |
|---|
| 420 | opr ^(self, b:Number):RR64 = |
|---|
| 421 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Pow") |
|---|
| 422 | (** Shouldn't need this extra declaration. **) |
|---|
| 423 | opr ^(self, b:AnyIntegral):RR64 = |
|---|
| 424 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Pow") |
|---|
| 425 | sin(self):RR64 = |
|---|
| 426 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sin") |
|---|
| 427 | cos(self):RR64 = |
|---|
| 428 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Cos") |
|---|
| 429 | tan(self):RR64 = |
|---|
| 430 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Tan") |
|---|
| 431 | asin(self):RR64 = |
|---|
| 432 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ASin") |
|---|
| 433 | acos(self):RR64 = |
|---|
| 434 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ACos") |
|---|
| 435 | atan(self):RR64 = |
|---|
| 436 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ATan") |
|---|
| 437 | atan2(self,x:Number):RR64 = |
|---|
| 438 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ATan2") |
|---|
| 439 | log(self):RR64 = |
|---|
| 440 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Log") |
|---|
| 441 | exp(self):RR64 = |
|---|
| 442 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Exp") |
|---|
| 443 | floor(self):RR64 = |
|---|
| 444 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Floor") |
|---|
| 445 | opr |\self/| : ZZ64 = |
|---|
| 446 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$IFloor") |
|---|
| 447 | ceiling(self):RR64 = |
|---|
| 448 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Ceiling") |
|---|
| 449 | opr |/self\| : ZZ64 = |
|---|
| 450 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ICeiling") |
|---|
| 451 | truncate(self):ZZ64 = |
|---|
| 452 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Truncate") |
|---|
| 453 | end |
|---|
| 454 | |
|---|
| 455 | trait RR64 extends Number comprises { Float, AnyIntegral, FloatLiteral } |
|---|
| 456 | (** returns true if the value is an IEEE NaN **) |
|---|
| 457 | getter isNaN(): Boolean = |
|---|
| 458 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$isNaN") |
|---|
| 459 | (** returns true if the value is an IEEE infinity **) |
|---|
| 460 | getter isInfinite(): Boolean = |
|---|
| 461 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$isInfinite") |
|---|
| 462 | (** returns true if the value is a valid number (not NaN) **) |
|---|
| 463 | getter isNumber(): Boolean = NOT self.isNaN |
|---|
| 464 | (** returns true if the value is finite **) |
|---|
| 465 | getter isFinite(): Boolean = NOT (self.isInfinite OR self.isNaN) |
|---|
| 466 | (** check returns Just(its argument) if it is finite, otherwise Nothing. **) |
|---|
| 467 | getter check(): Maybe[\RR64\] = |
|---|
| 468 | if self.isFinite then Just[\RR64\](self) else Nothing[\RR64\] end |
|---|
| 469 | (** check_star returns Just(its argument) if it is non-NaN, otherwise Nothing. **) |
|---|
| 470 | getter check_star(): Maybe[\RR64\] = |
|---|
| 471 | if self.isNaN then Nothing[\RR64\] else Just[\RR64\](self) end |
|---|
| 472 | (** obtain the raw bits of the IEEE floating-point representation of this value. **) |
|---|
| 473 | getter rawBits():ZZ64 = |
|---|
| 474 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$RawBits") |
|---|
| 475 | getter signBit():ZZ32 = if rawBits() < 0 then 1 else 0 end |
|---|
| 476 | (** next higher IEEE float **) |
|---|
| 477 | getter nextUp():RR64 = |
|---|
| 478 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NextUp") |
|---|
| 479 | (** next lower IEEE float **) |
|---|
| 480 | getter nextDown():RR64 = |
|---|
| 481 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NextDown") |
|---|
| 482 | (** %MINNUM% and %MAXNUM% return a numeric result where possible (avoiding NaN). |
|---|
| 483 | Note that %MINNUM% and %MAX% form a lattice with NaN at the top, and |
|---|
| 484 | that %MAXNUM% and %MIN% form a lattice with NaN at the bottom. **) |
|---|
| 485 | opr MINNUM(self, b:RR64):RR64 = do |
|---|
| 486 | r = self MIN b |
|---|
| 487 | if r.isNaN then |
|---|
| 488 | if self.isNumber then self |
|---|
| 489 | elif b.isNumber then b |
|---|
| 490 | else r end |
|---|
| 491 | else |
|---|
| 492 | r |
|---|
| 493 | end |
|---|
| 494 | end |
|---|
| 495 | opr MAXNUM(self, b:RR64):RR64 = do |
|---|
| 496 | r = self MAX b |
|---|
| 497 | if r.isNaN then |
|---|
| 498 | if self.isNumber then self |
|---|
| 499 | elif b.isNumber then b |
|---|
| 500 | else r end |
|---|
| 501 | else |
|---|
| 502 | r |
|---|
| 503 | end |
|---|
| 504 | end |
|---|
| 505 | (** returns a value of type RR32 **) |
|---|
| 506 | narrow(self): RR32 = |
|---|
| 507 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Narrow") |
|---|
| 508 | end |
|---|
| 509 | |
|---|
| 510 | trait QQ extends { RR64, StandardPartialOrder[\QQ\] } |
|---|
| 511 | getter zero(): QQ = 0 |
|---|
| 512 | getter one(): QQ = 1 |
|---|
| 513 | getter isNaN(): Boolean |
|---|
| 514 | getter isInfinite(): Boolean |
|---|
| 515 | getter isNumber(): Boolean = NOT self.isNaN |
|---|
| 516 | getter isFinite(): Boolean = (denominator(self) =/= 0) |
|---|
| 517 | numerator(self): ZZ |
|---|
| 518 | denominator(self): ZZ (* Ideally would be NN *) |
|---|
| 519 | opr |self| : QQ = |numerator(self)| / denominator(self) |
|---|
| 520 | (* Note that 0/0 = 0/0 is supposed to be true (//unlike// the behavior of floating-point NaN) *) |
|---|
| 521 | opr =(self, other:QQ):Boolean = |
|---|
| 522 | numerator(self) = numerator(other) AND: denominator(self) = denominator(other) |
|---|
| 523 | opr =/=(self, other:QQ):Boolean = NOT (self = other) |
|---|
| 524 | opr <(self, other:QQ):Boolean = do |
|---|
| 525 | (a, b) = (numerator(self), denominator(self)) |
|---|
| 526 | (c, d) = (numerator(other), denominator(other)) |
|---|
| 527 | (b=0 AND d=0 AND a=-1 AND c=1) OR (a d < b c) |
|---|
| 528 | end |
|---|
| 529 | opr <=(self, other:QQ):Boolean = (self < other) OR (self = other) |
|---|
| 530 | opr >(self, other:QQ):Boolean = (other < self) |
|---|
| 531 | opr >=(self, other:QQ):Boolean = (other <= self) |
|---|
| 532 | (** In case of 0/0, %MIN% and %MAX% return 0/0, otherwise it respects the |
|---|
| 533 | total order. **) |
|---|
| 534 | opr MIN(self, other:QQ):QQ = |
|---|
| 535 | if self < other then self elif other < self then other elif self = 0/0 then self else other end |
|---|
| 536 | opr MAX(self, other:QQ):QQ = |
|---|
| 537 | if self > other then self elif other > self then other elif self = 0/0 then self else other end |
|---|
| 538 | |
|---|
| 539 | opr -(self):QQ = (-numerator(self)) / denominator(self) |
|---|
| 540 | opr +(self,other:QQ):QQ = |
|---|
| 541 | if self = other AND denominator(self) = 0 then self else |
|---|
| 542 | (a, b) = (numerator(self), denominator(self)) |
|---|
| 543 | (c, d) = (numerator(other), denominator(other)) |
|---|
| 544 | (a d + b c) / b d |
|---|
| 545 | end |
|---|
| 546 | opr -(self,other:QQ):QQ = self + (-other) |
|---|
| 547 | opr DOT(self,other:QQ):QQ = do |
|---|
| 548 | (a, b) = (numerator(self), denominator(self)) |
|---|
| 549 | (c, d) = (numerator(other), denominator(other)) |
|---|
| 550 | a c / b d |
|---|
| 551 | end |
|---|
| 552 | opr TIMES(self,other:QQ):QQ = self DOT other |
|---|
| 553 | opr juxtaposition (self,other:QQ):QQ = self DOT other |
|---|
| 554 | opr /(self,other:QQ):QQ = do |
|---|
| 555 | (a, b) = (numerator(self), denominator(self)) |
|---|
| 556 | (c, d) = (numerator(other), denominator(other)) |
|---|
| 557 | a d / b c |
|---|
| 558 | end |
|---|
| 559 | opr ^(self, other:AnyIntegral):QQ = |
|---|
| 560 | if -other > 0 then (* Way too clever by half (to avoid infinite recursion on 2^(-63)) *) |
|---|
| 561 | (denominator(self)/numerator(self))^(-other) |
|---|
| 562 | else |
|---|
| 563 | (numerator(self))^other / (denominator(self))^other |
|---|
| 564 | end |
|---|
| 565 | floor(self):ZZ = if self < 0 then -ceiling(-self) else truncate(self) end |
|---|
| 566 | opr |\self/| : ZZ = floor(self) |
|---|
| 567 | ceiling(self):ZZ = if denominator(self) = 0 then self else |
|---|
| 568 | (a, b) = (numerator(self), denominator(self)) |
|---|
| 569 | if a < 0 then -floor(-self) else (a + b - 1) DIV b end |
|---|
| 570 | end |
|---|
| 571 | opr |/self\| : ZZ = ceiling(self) |
|---|
| 572 | truncate(self):ZZ = if denominator(self) = 0 then self else numerator(self) DIV denominator(self) end |
|---|
| 573 | round(self): ZZ = do x = self + 1/2; z = floor(x); if z = x AND odd z then z-1 else z end end |
|---|
| 574 | opr MINNUM(self, other:QQ):QQ = |
|---|
| 575 | if self < other then self elif other < self then other elif self = 0/0 then other else self end |
|---|
| 576 | opr MAXNUM(self, other:QQ):QQ = |
|---|
| 577 | if self > other then self elif other > self then other elif self = 0/0 then other else self end |
|---|
| 578 | end |
|---|
| 579 | |
|---|
| 580 | object Ratio(num: ZZ, den: ZZ) extends { QQ } |
|---|
| 581 | getter toString(): String = num.toString || "/" || den.toString |
|---|
| 582 | getter isNaN(): Boolean = (numerator(self) = 0 AND denominator(self) = 0) |
|---|
| 583 | getter isInfinite(): Boolean = (numerator(self) =/= 0 AND denominator(self) = 0) |
|---|
| 584 | numerator(self):ZZ = num |
|---|
| 585 | denominator(self):ZZ = den |
|---|
| 586 | end |
|---|
| 587 | |
|---|
| 588 | trait AnyIntegral extends { QQ } end |
|---|
| 589 | |
|---|
| 590 | trait Integral[\I extends Integral[\I\]\] extends { StandardTotalOrder[\I\], AnyIntegral } |
|---|
| 591 | getter zero(): I |
|---|
| 592 | getter one(): I |
|---|
| 593 | getter isNaN(): Boolean = false |
|---|
| 594 | getter isInfinite(): Boolean = false (* For now, no infinite integers. *) |
|---|
| 595 | denominator(self):ZZ = 1 |
|---|
| 596 | opr -(self):I |
|---|
| 597 | opr +(self,b:I):I |
|---|
| 598 | opr -(self,b:I):I |
|---|
| 599 | opr DOT(self,b:I):I |
|---|
| 600 | opr TIMES(self,b:I):I |
|---|
| 601 | opr juxtaposition(self,b:I):I |
|---|
| 602 | opr DIV(self,b:I):I |
|---|
| 603 | opr REM(self,b:I):I |
|---|
| 604 | opr MOD(self,b:I):I |
|---|
| 605 | opr GCD(self,b:I):I |
|---|
| 606 | opr LCM(self,b:I):I |
|---|
| 607 | opr DIVIDES(self,b:I):Boolean = b =/= zero() AND: (b MOD self) = zero() |
|---|
| 608 | opr CHOOSE(self,b:I):I |
|---|
| 609 | opr BITAND(self,b:I):I |
|---|
| 610 | opr BITOR(self,b:I):I |
|---|
| 611 | opr BITXOR(self,b:I):I |
|---|
| 612 | opr LSHIFT(self,b:AnyIntegral):I |
|---|
| 613 | opr RSHIFT(self,b:AnyIntegral):I |
|---|
| 614 | opr BITNOT(self):I |
|---|
| 615 | opr ^(self, b:AnyIntegral):RR64 |
|---|
| 616 | end |
|---|
| 617 | |
|---|
| 618 | trait ZZ32 extends { ZZ64, Integral[\ZZ32\] } comprises { Int, IntLiteral } |
|---|
| 619 | getter zero(): ZZ32 = 0 |
|---|
| 620 | getter one(): ZZ32 = 1 |
|---|
| 621 | getter minimum(): ZZ32 = -2147483647 - 1 |
|---|
| 622 | getter maximum(): ZZ32 = 2147483647 |
|---|
| 623 | |
|---|
| 624 | opr |self| : ZZ32 = if self>=0 then self else -self end |
|---|
| 625 | opr =(self, b:ZZ32):Boolean = |
|---|
| 626 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Eq") |
|---|
| 627 | opr <(self, b:ZZ32):Boolean = |
|---|
| 628 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Less") |
|---|
| 629 | |
|---|
| 630 | opr -(self):ZZ32 = |
|---|
| 631 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Negate") |
|---|
| 632 | opr +(self,b:ZZ32):ZZ32 = |
|---|
| 633 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Add") |
|---|
| 634 | opr -(self,b:ZZ32):ZZ32 = |
|---|
| 635 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Sub") |
|---|
| 636 | opr DOT(self,b:ZZ32):ZZ32 = |
|---|
| 637 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul") |
|---|
| 638 | opr TIMES(self,b:ZZ32):ZZ32 = |
|---|
| 639 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul") |
|---|
| 640 | opr juxtaposition(self,b:ZZ32):ZZ32 = |
|---|
| 641 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul") |
|---|
| 642 | opr DIV(self,b:ZZ32):ZZ32 = |
|---|
| 643 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Div") |
|---|
| 644 | opr REM(self,b:ZZ32):ZZ32 = |
|---|
| 645 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Rem") |
|---|
| 646 | opr MOD(self,b:ZZ32):ZZ32 = |
|---|
| 647 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mod") |
|---|
| 648 | opr GCD(self,b:ZZ32):ZZ32 = |
|---|
| 649 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Gcd") |
|---|
| 650 | opr LCM(self,b:ZZ32):ZZ32 = |
|---|
| 651 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Lcm") |
|---|
| 652 | opr CHOOSE(self,b:ZZ32):ZZ32 = |
|---|
| 653 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Choose") |
|---|
| 654 | opr BITAND(self,b:ZZ32):ZZ32 = |
|---|
| 655 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitAnd") |
|---|
| 656 | opr BITOR(self,b:ZZ32):ZZ32 = |
|---|
| 657 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitOr") |
|---|
| 658 | opr BITXOR(self,b:ZZ32):ZZ32 = |
|---|
| 659 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitXor") |
|---|
| 660 | opr LSHIFT(self,b:ZZ64):ZZ32 = |
|---|
| 661 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$LShift") |
|---|
| 662 | opr RSHIFT(self,b:ZZ64):ZZ32 = |
|---|
| 663 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$RShift") |
|---|
| 664 | opr BITNOT(self):ZZ32 = |
|---|
| 665 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitNot") |
|---|
| 666 | opr ^(self, b:AnyIntegral):RR64 = |
|---|
| 667 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Pow") |
|---|
| 668 | widen(self):ZZ64 = |
|---|
| 669 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$ToLong") |
|---|
| 670 | partitionL(self):ZZ32 = |
|---|
| 671 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Partition") |
|---|
| 672 | unsigned(self):NN32 = |
|---|
| 673 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.ZZ32$ToNN32") |
|---|
| 674 | end |
|---|
| 675 | |
|---|
| 676 | trait ZZ64 extends { ZZ, Integral[\ZZ64\] } comprises { Long, ZZ32 } |
|---|
| 677 | getter zero(): ZZ64 = widen(0) |
|---|
| 678 | getter one(): ZZ64 = widen(1) |
|---|
| 679 | getter minimum(): ZZ64 = -9223372036854775807 - 1 |
|---|
| 680 | getter maximum(): ZZ64 = 9223372036854775807 |
|---|
| 681 | |
|---|
| 682 | opr |x:ZZ64| : ZZ64 = if x>=0 then x else -x end |
|---|
| 683 | |
|---|
| 684 | opr =(self, b:ZZ64):Boolean = |
|---|
| 685 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Eq") |
|---|
| 686 | opr <(self, b:ZZ64):Boolean = |
|---|
| 687 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Less") |
|---|
| 688 | (* Argh! Due to method ambiguities with ZZ, these definitions must be given |
|---|
| 689 | explicitly here. *) |
|---|
| 690 | opr >(self, b:ZZ64):Boolean = b < self |
|---|
| 691 | opr >=(self, b:ZZ64):Boolean = NOT (self < b) |
|---|
| 692 | opr <=(self, b:ZZ64):Boolean = NOT (b < self) |
|---|
| 693 | opr CMP(self, b:ZZ64): TotalComparison = |
|---|
| 694 | if self < b then LessThan |
|---|
| 695 | elif b < self then GreaterThan |
|---|
| 696 | else EqualTo end |
|---|
| 697 | |
|---|
| 698 | opr -(self):ZZ64 = |
|---|
| 699 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Negate") |
|---|
| 700 | opr +(self,b:ZZ64):ZZ64 = |
|---|
| 701 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Add") |
|---|
| 702 | opr -(self,b:ZZ64):ZZ64 = |
|---|
| 703 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Sub") |
|---|
| 704 | opr DOT(self,b:ZZ64):ZZ64 = |
|---|
| 705 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul") |
|---|
| 706 | opr TIMES(self,b:ZZ64):ZZ64 = |
|---|
| 707 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul") |
|---|
| 708 | opr juxtaposition(self,b:ZZ64):ZZ64 = |
|---|
| 709 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul") |
|---|
| 710 | opr DIV(self,b:ZZ64):ZZ64 = |
|---|
| 711 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Div") |
|---|
| 712 | opr REM(self,b:ZZ64):ZZ64 = |
|---|
| 713 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Rem") |
|---|
| 714 | opr MOD(self,b:ZZ64):ZZ64 = |
|---|
| 715 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mod") |
|---|
| 716 | opr GCD(self,b:ZZ64):ZZ64 = |
|---|
| 717 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Gcd") |
|---|
| 718 | opr LCM(self,b:ZZ64):ZZ64 = |
|---|
| 719 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Lcm") |
|---|
| 720 | opr CHOOSE(self,b:ZZ64):ZZ64 = |
|---|
| 721 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Choose") |
|---|
| 722 | opr BITAND(self,b:ZZ64):ZZ64 = |
|---|
| 723 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitAnd") |
|---|
| 724 | opr BITOR(self,b:ZZ64):ZZ64 = |
|---|
| 725 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitOr") |
|---|
| 726 | opr BITXOR(self,b:ZZ64):ZZ64 = |
|---|
| 727 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitXor") |
|---|
| 728 | opr LSHIFT(self,b:AnyIntegral):ZZ64 = |
|---|
| 729 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$LShift") |
|---|
| 730 | opr RSHIFT(self,b:AnyIntegral):ZZ64 = |
|---|
| 731 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$RShift") |
|---|
| 732 | opr BITNOT(self):ZZ64 = |
|---|
| 733 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitNot") |
|---|
| 734 | opr ^(self, b:AnyIntegral):RR64 = |
|---|
| 735 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Pow") |
|---|
| 736 | partitionL(self):ZZ64 = |
|---|
| 737 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Partition") |
|---|
| 738 | narrow(self):ZZ32 = |
|---|
| 739 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$FromLong") |
|---|
| 740 | unsigned(self):NN64 = |
|---|
| 741 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$ToUnsignedLong") |
|---|
| 742 | big(self):ZZ = |
|---|
| 743 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$ToBigNum") |
|---|
| 744 | end |
|---|
| 745 | |
|---|
| 746 | trait NN64 extends { ZZ, Integral[\NN64\] } comprises { UnsignedLong, NN32 } |
|---|
| 747 | opr |self| : NN64 = self |
|---|
| 748 | opr =(self, b:NN64):Boolean = |
|---|
| 749 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Eq") |
|---|
| 750 | opr <(self, b:NN64):Boolean = |
|---|
| 751 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Less") |
|---|
| 752 | opr -(self):NN64 = |
|---|
| 753 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Negate") |
|---|
| 754 | opr +(self,b:NN64):NN64 = |
|---|
| 755 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Add") |
|---|
| 756 | opr -(self,b:NN64):NN64 = |
|---|
| 757 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Sub") |
|---|
| 758 | opr DOT(self,b:NN64):NN64 = |
|---|
| 759 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul") |
|---|
| 760 | opr TIMES(self,b:NN64):NN64 = |
|---|
| 761 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul") |
|---|
| 762 | opr juxtaposition(self,b:NN64):NN64 = |
|---|
| 763 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul") |
|---|
| 764 | opr DIV(self,b:NN64):NN64 = |
|---|
| 765 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Div") |
|---|
| 766 | opr REM(self,b:NN64):NN64 = |
|---|
| 767 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Rem") |
|---|
| 768 | opr MOD(self,b:NN64):NN64 = |
|---|
| 769 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mod") |
|---|
| 770 | opr GCD(self,b:NN64):NN64 = |
|---|
| 771 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Gcd") |
|---|
| 772 | opr LCM(self,b:NN64):NN64 = |
|---|
| 773 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Lcm") |
|---|
| 774 | opr CHOOSE(self,b:NN64):NN64 = |
|---|
| 775 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Choose") |
|---|
| 776 | opr BITAND(self,b:NN64):NN64 = |
|---|
| 777 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitAnd") |
|---|
| 778 | opr BITOR(self,b:NN64):NN64 = |
|---|
| 779 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitOr") |
|---|
| 780 | opr BITXOR(self,b:NN64):NN64 = |
|---|
| 781 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitXor") |
|---|
| 782 | opr LSHIFT(self,b:AnyIntegral):NN64 = |
|---|
| 783 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$LShift") |
|---|
| 784 | opr RSHIFT(self,b:AnyIntegral):NN64 = |
|---|
| 785 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$RShift") |
|---|
| 786 | opr BITNOT(self):NN64 = |
|---|
| 787 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitNot") |
|---|
| 788 | opr ^(self, b:AnyIntegral):RR64 = |
|---|
| 789 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Pow") |
|---|
| 790 | partitionL(self):NN64 = |
|---|
| 791 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Partition") |
|---|
| 792 | narrow(self):NN32 = |
|---|
| 793 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$FromLong") |
|---|
| 794 | signed(self):NN64 = |
|---|
| 795 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$ToLong") |
|---|
| 796 | end |
|---|
| 797 | |
|---|
| 798 | trait ZZ extends Integral[\ZZ\] |
|---|
| 799 | comprises { BigNum, ZZ64 } |
|---|
| 800 | getter zero(): ZZ = |
|---|
| 801 | 1934791870947204798109283471902037419 - 1934791870947204798109283471902037419 |
|---|
| 802 | getter one(): ZZ = zero() + 1 |
|---|
| 803 | numerator(self):ZZ = self |
|---|
| 804 | opr |self| : ZZ32 = if self>=0 then self else -self end |
|---|
| 805 | opr =(self, b: ZZ):Boolean = |
|---|
| 806 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Eq") |
|---|
| 807 | opr <(self, other:ZZ): Boolean = self.cmp(other) < 0 |
|---|
| 808 | opr <=(self, other:ZZ): Boolean = self.cmp(other) <= 0 |
|---|
| 809 | opr >(self, other:ZZ): Boolean = self.cmp(other) > 0 |
|---|
| 810 | opr >=(self, other:ZZ): Boolean = self.cmp(other) >= 0 |
|---|
| 811 | opr CMP(self, other:ZZ): TotalComparison = self.cmp(other) CMP 0 |
|---|
| 812 | cmp(b:ZZ): ZZ32 = |
|---|
| 813 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Cmp") |
|---|
| 814 | |
|---|
| 815 | opr -(self): ZZ = |
|---|
| 816 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Negate") |
|---|
| 817 | opr +(self, b: ZZ): ZZ = |
|---|
| 818 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Add") |
|---|
| 819 | opr -(self, b: ZZ): ZZ = |
|---|
| 820 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Sub") |
|---|
| 821 | opr DOT(self, b: ZZ): ZZ = |
|---|
| 822 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul") |
|---|
| 823 | opr juxtaposition(self, b: ZZ): ZZ = |
|---|
| 824 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul") |
|---|
| 825 | opr TIMES(self, b: ZZ): ZZ = |
|---|
| 826 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul") |
|---|
| 827 | opr /(self,other:ZZ):QQ = if other < 0 then (-self)/(-other) else |
|---|
| 828 | g = self GCD other |
|---|
| 829 | if g=0 then Ratio(0,0) else |
|---|
| 830 | a = self DIV g |
|---|
| 831 | b = other DIV g |
|---|
| 832 | if b = 1 then a else Ratio(a,b) end |
|---|
| 833 | end |
|---|
| 834 | end |
|---|
| 835 | opr DIV(self, b: ZZ): ZZ = |
|---|
| 836 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Div") |
|---|
| 837 | opr REM(self, b: ZZ): ZZ = |
|---|
| 838 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Rem") |
|---|
| 839 | opr MOD(self, b: ZZ): ZZ = |
|---|
| 840 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mod") |
|---|
| 841 | opr GCD(self, b: ZZ): ZZ = |
|---|
| 842 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Gcd") |
|---|
| 843 | opr LCM(self, b: ZZ): ZZ = |
|---|
| 844 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Lcm") |
|---|
| 845 | opr CHOOSE(self, b: ZZ): ZZ = |
|---|
| 846 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Choose") |
|---|
| 847 | opr BITAND(self, b: ZZ): ZZ = |
|---|
| 848 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitAnd") |
|---|
| 849 | opr BITOR(self, b: ZZ): ZZ = |
|---|
| 850 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitOr") |
|---|
| 851 | opr BITXOR(self, b: ZZ): ZZ = |
|---|
| 852 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitXor") |
|---|
| 853 | opr LSHIFT(self, b:AnyIntegral): ZZ = |
|---|
| 854 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$LShift") |
|---|
| 855 | opr RSHIFT(self, b:AnyIntegral): ZZ = |
|---|
| 856 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$RShift") |
|---|
| 857 | opr BITNOT(self): ZZ = |
|---|
| 858 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitNot") |
|---|
| 859 | opr ^(self, b:AnyIntegral):RR64 = |
|---|
| 860 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Pow") |
|---|
| 861 | odd(self): Boolean = NOT (even self) |
|---|
| 862 | even(self): Boolean = (self MOD 2) = 0 |
|---|
| 863 | end |
|---|
| 864 | |
|---|
| 865 | (************************************************************ |
|---|
| 866 | * Generator support |
|---|
| 867 | ************************************************************) |
|---|
| 868 | |
|---|
| 869 | (** Generator |
|---|
| 870 | * |
|---|
| 871 | * We say an object which extends Generator[\T\] "generates objects of |
|---|
| 872 | * type T." |
|---|
| 873 | * |
|---|
| 874 | * Generators are used to express iteration in Fortress. Every |
|---|
| 875 | * generated expression in Fortress (eg for loop, comprehension) is |
|---|
| 876 | * desugared into calls to methods of Generator, chiefly the generate |
|---|
| 877 | * method. |
|---|
| 878 | * |
|---|
| 879 | * Every generator has a notion of a "natural order" (which by default is |
|---|
| 880 | * unspecified), which describes the ordering of reduction operations, |
|---|
| 881 | * and also describes the order in which elements are produced by the |
|---|
| 882 | * sequential version of the same generator (given by the seq(self) |
|---|
| 883 | * method). The default implementation of seq(self) guarantees that these |
|---|
| 884 | * orders will match. |
|---|
| 885 | * |
|---|
| 886 | * Note in particular that the natural order of a Generator must be |
|---|
| 887 | * consistent; that is, if a SEQV b then a and b must yield SEQV |
|---|
| 888 | * elements in the same natural order. However, note that unless a type |
|---|
| 889 | * specifically documents otherwise, no particular element ordering is |
|---|
| 890 | * guaranteed, nor is it necessary to guarantee that a=b have the same |
|---|
| 891 | * natural order when equality is defined. |
|---|
| 892 | * |
|---|
| 893 | * Note that more complex derived generators are specified further |
|---|
| 894 | * down in the definition of Generator. These have the same notions |
|---|
| 895 | * of natural order and by default are defined in terms of the |
|---|
| 896 | * generate() method. |
|---|
| 897 | * |
|---|
| 898 | * Minimal complete definition of a Generator is the generate(...) method. |
|---|
| 899 | *) |
|---|
| 900 | trait Generator[\E\] |
|---|
| 901 | excludes { Number } |
|---|
| 902 | (** generate is the core of Generator. It generates elements of |
|---|
| 903 | type E and passes them to the body function. This generation |
|---|
| 904 | can occur using any mixture of serial and parallel execution |
|---|
| 905 | desired by the author of the generator; by default uses of a |
|---|
| 906 | generator must assume every call to the body occurs in |
|---|
| 907 | parallel. |
|---|
| 908 | |
|---|
| 909 | The results of generation are combined using the reduction |
|---|
| 910 | object R, which specifies a monoidal operation (associative |
|---|
| 911 | and with an identity). Body results must be combined together |
|---|
| 912 | following the natural order of the generator. The author of |
|---|
| 913 | the generator is free to use the identity element anywhere |
|---|
| 914 | desired in this computation, and to group reductions in any |
|---|
| 915 | way desired; if no elements are generated the identity must be |
|---|
| 916 | returned. *) |
|---|
| 917 | generate[\R\](r: Reduction[\R\], body: E->R): R |
|---|
| 918 | |
|---|
| 919 | (** Transforming generators into new generators *) |
|---|
| 920 | (** map applies a function f to each element generated and yields |
|---|
| 921 | the result. The resulting generator must have the same |
|---|
| 922 | ordering and cross product properties as the generator from |
|---|
| 923 | which it is derived. *) |
|---|
| 924 | map[\G\](f: E->G): Generator[\G\] = SimpleMappedGenerator[\E,G\](self,f) |
|---|
| 925 | (** seq produces a sequential version of the same generator, in |
|---|
| 926 | which elements are produced in the generator's natural order. *) |
|---|
| 927 | seq(self): SequentialGenerator[\E\] = NaiveSeqGenerator[\E\](self) |
|---|
| 928 | |
|---|
| 929 | (** Nesting of two generators; the innermost is data-dependent |
|---|
| 930 | upon the outer one. This is specifically designed to be |
|---|
| 931 | overloaded so that the combined generators have properties |
|---|
| 932 | appropriate to the pairing. Because of the data dependency |
|---|
| 933 | the natural order of the nesting is the natural order of the |
|---|
| 934 | inner generators, in the natural order the outer nesting |
|---|
| 935 | produces them. So for example, if we write: |
|---|
| 936 | (0#3).nest[\ZZ32\](\(n:ZZ32):Generator[\ZZ32\] => (n*100#4)) |
|---|
| 937 | then the natural order is 0,1,2,3,100,101,102,103,200,201,202,203 |
|---|
| 938 | **) |
|---|
| 939 | nest[\G\](f: E -> Generator[\G\]): Generator[\G\] = |
|---|
| 940 | SimpleNestedGenerator[\E,G\](self,f) |
|---|
| 941 | |
|---|
| 942 | (** Filtering data from a generator. Only elements that satisfy |
|---|
| 943 | the predicate p are retained. Natural order and cross product |
|---|
| 944 | properties are otherwise preserved. **) |
|---|
| 945 | filter(f: E -> Condition[\()\]): Generator[\E\] = |
|---|
| 946 | SimpleFilterGenerator[\E\](self,f) |
|---|
| 947 | |
|---|
| 948 | (** Cross product of two generators. This is specifically |
|---|
| 949 | designed to be overloaded, such that pairs of independent |
|---|
| 950 | generators can be combined to produce a generator which |
|---|
| 951 | possibly interleaves the iteration spaces of the two |
|---|
| 952 | generators. For example, we might combine (0#16).cross(0#32) |
|---|
| 953 | such that it first splits the second range in half, then the |
|---|
| 954 | first range in half, then the second, and so forth. |
|---|
| 955 | |
|---|
| 956 | Consider a grid for which the rows are labeled from top to |
|---|
| 957 | bottom with the elements of a in natural order, and the |
|---|
| 958 | columns are labeled from left to right with the elements of g |
|---|
| 959 | in natural order. Each point in the grid corresponds to a |
|---|
| 960 | pair (a,b) that must be generated by self.cross(g). In the |
|---|
| 961 | natural order of the cross product, an element must occur |
|---|
| 962 | after those that lie above and to the left of it in the grid. |
|---|
| 963 | By default the natural order of the cross product is |
|---|
| 964 | left-to-right, top to bottom. Programmers must not rely on |
|---|
| 965 | the default order, except that cross products involving one or |
|---|
| 966 | more sequential generators are always performed in the default |
|---|
| 967 | order. Note that this means that the following have the same |
|---|
| 968 | natural order: |
|---|
| 969 | seq(a).cross(b) |
|---|
| 970 | a.cross(seq(b)) |
|---|
| 971 | seq(a).cross(seq(b)) |
|---|
| 972 | But seq(a.cross(b)) may have a different natural order. *) |
|---|
| 973 | cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] = |
|---|
| 974 | SimplePairGenerator[\E,G\](self, g) |
|---|
| 975 | |
|---|
| 976 | (** Derived generation operations *) |
|---|
| 977 | (** mapReduce is equivalent to generate, but takes an explicit join |
|---|
| 978 | and zero which can have any type. It still assumes join is |
|---|
| 979 | associative and that zero is the identity of join. **) |
|---|
| 980 | mapReduce[\R\](body: E->R, join:(R,R)->R, id:R): R = |
|---|
| 981 | generate[\R\](MapReduceReduction[\R\](join,id), body) |
|---|
| 982 | (** reduce works much like generate or mapReduce, |
|---|
| 983 | but has no body expression **) |
|---|
| 984 | reduce(j:(E,E)->E, z:E):E = mapReduce[\E\](fn (e:E)=>e, j, z) |
|---|
| 985 | reduce(r: Reduction[\E\]):E = generate[\E\](r, fn(e:E)=>e) |
|---|
| 986 | (** loop is a version of generate which discards the void results |
|---|
| 987 | of the body computation. It is used to translated |
|---|
| 988 | reduction-variable-free for loops. **) |
|---|
| 989 | loop(f:E->()): () = generate[\()\](VoidReduction, f) |
|---|
| 990 | (** Is x generated by this generator? **) |
|---|
| 991 | opr IN(x:E, self): Boolean = BIG OR [y <- self] x=y |
|---|
| 992 | (** The MATCH operator is used (as a temporary hack) by CASE when the |
|---|
| 993 | match clause is a Generator[\E\]. We must choose either =, SEQV, or |
|---|
| 994 | IN as appropriate, depending on the type of the LHS. **) |
|---|
| 995 | opr MATCH(x:Any, self): Boolean = |
|---|
| 996 | typecase x of |
|---|
| 997 | E => (x IN self) |
|---|
| 998 | Generator[\E\] => (x = self) |
|---|
| 999 | else => fail("Type error in MATCH of Generator") |
|---|
| 1000 | end |
|---|
| 1001 | end |
|---|
| 1002 | |
|---|
| 1003 | (** The following top-level functions are used as glue in the |
|---|
| 1004 | desugaring of generated expressions (comprehensions, BIG |
|---|
| 1005 | operators, and loops). They exist at the top level in part to |
|---|
| 1006 | work around shortcomings in the ablity of the Fortress interpreter |
|---|
| 1007 | to check types dynamically for anything except top-level |
|---|
| 1008 | non-overloaded function calls. **) |
|---|
| 1009 | __generate[\E,R\](g:Generator[\E\], r: Reduction[\R\], b:E->R): R = |
|---|
| 1010 | g.generate[\R\](r,b) |
|---|
| 1011 | |
|---|
| 1012 | __nest[\E1,E2\](g:Generator[\E1\], f:E1->Generator[\E2\]):Generator[\E2\] = |
|---|
| 1013 | g.nest[\E2\](f) |
|---|
| 1014 | |
|---|
| 1015 | __singleton[\E\](body:E): Generator[\E\] = Just[\E\](body) |
|---|
| 1016 | |
|---|
| 1017 | __loop[\E,R\](g:Generator[\E\], body:E->R): () = g.loop(body) |
|---|
| 1018 | |
|---|
| 1019 | __cond[\E,R\](c:Condition[\E\], t:E->R, e:()->R): R = c.cond[\R\](t,e) |
|---|
| 1020 | __cond[\E\](c:Condition[\E\], t:E->()): () = c.cond[\()\](t, fn () => ()) |
|---|
| 1021 | |
|---|
| 1022 | (** Used in desugaring binding %while% **) |
|---|
| 1023 | __whileCond[\E\](c:Condition[\E\], b:E->()): () = |
|---|
| 1024 | c.cond[\Boolean\](fn (e): Boolean => do b(e); true end, fn ():Boolean => false) |
|---|
| 1025 | |
|---|
| 1026 | (** Unlike the user-visible dotted map method, this method is used for |
|---|
| 1027 | the internals of comprehension desugaring [except that at present |
|---|
| 1028 | it is not actually in use, but we're planning to use it]. As a |
|---|
| 1029 | result we know that its result will immediately be consumed, and |
|---|
| 1030 | we should *not* create an intermediate collection if we're passed |
|---|
| 1031 | a collection. **) |
|---|
| 1032 | __map[\E,R\](g:Generator[\E\], f:E->R): Generator[\R\] = |
|---|
| 1033 | typecase g of |
|---|
| 1034 | SomeMappedGenerator[\E\] => g.map[\R\](f) |
|---|
| 1035 | SequentialGenerator[\E\] => SimpleMappedSeqGenerator[\E,R\](g,f) |
|---|
| 1036 | else => SimpleMappedGenerator[\E,R\](g,f) |
|---|
| 1037 | end |
|---|
| 1038 | |
|---|
| 1039 | (** Unlike the user-visible dotted filter method, but like the __map |
|---|
| 1040 | method, this method is intended for use in the internals of |
|---|
| 1041 | comprehension desugaring. Again its result will immediately be |
|---|
| 1042 | consumed, and we do not create an intermediate collection but |
|---|
| 1043 | perform the filtering lazily on demand. **) |
|---|
| 1044 | __filter[\E\](g:Generator[\E\], p:E->Condition[\()\]): Generator[\E\] = |
|---|
| 1045 | typecase g of |
|---|
| 1046 | FilterGenerator[\E\] => g.filter(p) |
|---|
| 1047 | SequentialGenerator[\E\] => SimpleSeqFilterGenerator[\E\](g,p) |
|---|
| 1048 | else => SimpleFilterGenerator[\E\](g,p) |
|---|
| 1049 | end |
|---|
| 1050 | |
|---|
| 1051 | (** Application of a BIG operator, the topmost level of comprehension desugaring. **) |
|---|
| 1052 | __bigOperator[\I,O,R,L\](o:BigOperator[\I,O,R,L\],desugaredClauses:(Reduction[\L\],I->L)->L): O = do |
|---|
| 1053 | r = o.reduction() |
|---|
| 1054 | body(i): L = r.lift((o.body())(i)) |
|---|
| 1055 | (o.unwrap())(r.unlift(desugaredClauses(r,body))) |
|---|
| 1056 | end |
|---|
| 1057 | |
|---|
| 1058 | (** Application of two nested BIG operators, possibly with fusion. This only covers |
|---|
| 1059 | a comprehension of the form: |
|---|
| 1060 | BIG outer [ xs <- expr_o ] (BIG inner [x <- xs] expr_i) |
|---|
| 1061 | The desugarer extracts comprehensions of this form from more complex nests of |
|---|
| 1062 | comprehensions, using a combination of splitting: |
|---|
| 1063 | BIG OP [ gs_1, gs_2 ] expr = BIG OP [ gs_1 ] (BIG OP [ gs_2 ] expr) |
|---|
| 1064 | and filter squeezing: |
|---|
| 1065 | BIG OP [ xs <- g, p(xs) ] expr = BIG OP [ xs <- g.filter(p) ] expr |
|---|
| 1066 | There are some big caveats to this explanation in practice. Most important is that |
|---|
| 1067 | we don't unlift and lift or do input/output conversion except where neccessary, so |
|---|
| 1068 | splitting skips these operations in between the inner and outer comprehension. |
|---|
| 1069 | **) |
|---|
| 1070 | __bigOperator2[\I,M,O,R1,L1,R2,L2,E\](outer:BigOperator[\M,O,R1,L1\], |
|---|
| 1071 | inner:BigOperator[\I,M,R2,L2\], |
|---|
| 1072 | gg: Generator[\Generator[\E\]\], |
|---|
| 1073 | innerBody:E->L2): L1 = do |
|---|
| 1074 | o = outer.reduction() |
|---|
| 1075 | i = inner.reduction() |
|---|
| 1076 | gg.generate(o,fn (xs) => |
|---|
| 1077 | o.lift((outer.wrap())((inner.unwrap())(i.unlift( |
|---|
| 1078 | xs.generate(i,innerBody)))))) |
|---|
| 1079 | end |
|---|
| 1080 | |
|---|
| 1081 | trait SequentialGenerator[\E\] extends { Generator[\E\] } |
|---|
| 1082 | seq(self) = self |
|---|
| 1083 | map[\G\](f: E->G): SequentialGenerator[\G\] = |
|---|
| 1084 | SimpleMappedSeqGenerator[\E,G\](self,f) |
|---|
| 1085 | (* TODO: make overloaded *) |
|---|
| 1086 | nest[\G\](f: E -> Generator[\G\]): Generator[\G\] = |
|---|
| 1087 | typecase f of |
|---|
| 1088 | E -> SequentialGenerator[\G\] => |
|---|
| 1089 | SimpleNestedSeqGenerator[\E,G\](self,f) |
|---|
| 1090 | else => SimpleNestedGenerator[\E,G\](self,f) |
|---|
| 1091 | end |
|---|
| 1092 | (* TODO: make overloaded *) |
|---|
| 1093 | cross[\F\](g:Generator[\F\]): Generator[\(E,F)\] = |
|---|
| 1094 | typecase g of |
|---|
| 1095 | SequentialGenerator[\F\] => |
|---|
| 1096 | SimplePairSeqGenerator[\E,F\](self,g) |
|---|
| 1097 | else => SimplePairGenerator[\E,F\](self,g) |
|---|
| 1098 | end |
|---|
| 1099 | end |
|---|
| 1100 | |
|---|
| 1101 | (** A Condition is a Generator that generates 0 or 1 element. |
|---|
| 1102 | Conditions can be used as nullary comprehension generators or |
|---|
| 1103 | as predicates in an if expression. **) |
|---|
| 1104 | trait Condition[\E\] extends { ZeroIndexed[\E\], SequentialGenerator[\E\] } |
|---|
| 1105 | getter isEmpty(): Boolean = NOT holds() |
|---|
| 1106 | getter nonEmpty(): Boolean = NOT isEmpty() |
|---|
| 1107 | getter holds(): Boolean = cond[\Boolean\](fn (_:E):Boolean => true, fn () => false) |
|---|
| 1108 | getter size(): ZZ32 = if holds() then 1 else 0 end |
|---|
| 1109 | getter get(): E throws NotFound = cond[\E\](identity[\E\], fn () => throw NotFound) |
|---|
| 1110 | getter bounds(): FullRange[\ZZ32,true\] = 0 # |self| |
|---|
| 1111 | getter indices(): FullRange[\ZZ32,true\] = bounds() |
|---|
| 1112 | getter indexValuePairs(): Condition[\(ZZ32,E)\] = |
|---|
| 1113 | cond[\E\](fn (e:E) => Just[\(ZZ32,E)\](0,e), fn () => Nothing[\(ZZ32,E)\]) |
|---|
| 1114 | opr |self|: ZZ32 = if holds() then 1 else 0 end |
|---|
| 1115 | opr [i:ZZ32]:E throws NotFound = if i=0 then get() else throw NotFound end |
|---|
| 1116 | opr [r:Range[\ZZ32\]]: Condition[\E\] = |
|---|
| 1117 | cond[\E\](fn (e:E): Condition[\E\] => do |
|---|
| 1118 | r1 = (0#1)[r] |
|---|
| 1119 | if r1.isEmpty then Nothing[\E\] else self end |
|---|
| 1120 | end, |
|---|
| 1121 | fn (): Condition[\E\] => do r1 = (0#0)[r]; self end) |
|---|
| 1122 | getDefault(e:E): E = cond[\E\](identity[\E\], fn () => e) |
|---|
| 1123 | cond[\G\](t: E -> G, e: () -> G): G |
|---|
| 1124 | generate[\G\](r:Reduction[\G\], body: E -> G): G = cond[\G\](body,fn () => r.empty()) |
|---|
| 1125 | |
|---|
| 1126 | (** For a Condition, these methods run eagerly. **) |
|---|
| 1127 | map[\G\](f: E->G): Condition[\G\] = |
|---|
| 1128 | cond[\G\](fn (e:E) => Just[\G\](f(e)), fn () => Nothing[\G\]) |
|---|
| 1129 | ivmap[\G\](f: (ZZ32,E)->G): Condition[\G\] = |
|---|
| 1130 | cond[\G\](fn (e:E) => Just[\G\](f(0,e)), fn () => Nothing[\G\]) |
|---|
| 1131 | nest[\G\](f: E -> Generator[\G\]): Generator[\G\] = |
|---|
| 1132 | cond[\G\](f, fn () => Nothing[\G\]) |
|---|
| 1133 | cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] = |
|---|
| 1134 | cond[\G\](fn (e:E):Generator[\(E,G)\] => g.map[\(E,G)\](fn (g':G):(E,G) => (e,g')), |
|---|
| 1135 | fn () => Nothing[\(E,G)\]) |
|---|
| 1136 | mapReduce[\R\](body: E->R, _:(R,R)->R, id:R): R = |
|---|
| 1137 | cond[\R\](body, fn () => id) |
|---|
| 1138 | reduce(_:(E,E)->E, z:E):E = cond[\E\](identity[\E\], fn ():E => z) |
|---|
| 1139 | reduce(r: Reduction[\E\]):E = cond[\E\](identity[\E\], fn ():E => r.empty()) |
|---|
| 1140 | loop(f:E->()): () = cond[\()\](f,fn ():() => ()) |
|---|
| 1141 | opr IN(x:E, self):Boolean = cond[\Boolean\](fn (e:E):Boolean => x=e, fn () => false) |
|---|
| 1142 | end |
|---|
| 1143 | |
|---|
| 1144 | (** Conjunction and disjunction of condition functions **) |
|---|
| 1145 | opr ANDCOND[\I\](p1:I->Condition[\()\], p2:I->Condition[\()\]): I->Condition[\()\] = |
|---|
| 1146 | fn (i:I):Boolean => p1(i).holds AND: p2(i).holds |
|---|
| 1147 | |
|---|
| 1148 | (** Conjunction and disjunction of condition functions **) |
|---|
| 1149 | opr ORCOND[\I\](p1:I->Condition[\()\], p2:I->Condition[\()\]): I->Condition[\()\] = |
|---|
| 1150 | fn (i:I):Boolean => p1(i).holds OR: p2(i).holds |
|---|
| 1151 | |
|---|
| 1152 | (** Operations which use generation internally. Should be functional |
|---|
| 1153 | methods of Generator, but that didn't work when last tested. **) |
|---|
| 1154 | |
|---|
| 1155 | (** IN returns true if any element generated by its second argument is |
|---|
| 1156 | = to its first argument. x NOTIN g is simply NOT (x IN g). |
|---|
| 1157 | Unless documented otherwise, this is O(n) for an n-element |
|---|
| 1158 | Generator (it simply performs naive matching). **) |
|---|
| 1159 | opr NOTIN[\E\](x: E, this: Generator[\E\]): Boolean = NOT (x IN this) |
|---|
| 1160 | |
|---|
| 1161 | (* seq[\T\](g:Generator[\T\]):SequentialGenerator[\T\] = g.seq() *) |
|---|
| 1162 | sequential[\T\](g:Generator[\T\]):SequentialGenerator[\T\] = seq(g) |
|---|
| 1163 | |
|---|
| 1164 | (************************************************************ |
|---|
| 1165 | * Meta-generators: BIG GENERATOR |
|---|
| 1166 | ************************************************************) |
|---|
| 1167 | |
|---|
| 1168 | (** The problem: Your code is sprinkled with the same generator code, |
|---|
| 1169 | over and over again. Maybe it looks something like this: |
|---|
| 1170 | % for (i,v) <- a.indexValuePairs, v =/= 0, j <- 0:i do (code using i and j) % |
|---|
| 1171 | You goal: abstract this into a single generator. You can do this as follows: |
|---|
| 1172 | % usefulGen = BIG GENERATOR[(i,v) <- a.indexValuePairs, v =/= 0, j <- 0:i] (i,j) % |
|---|
| 1173 | Not much savings there, but the important part is that you can just |
|---|
| 1174 | cut and paste the generators from the original code. And all occurrences |
|---|
| 1175 | can be cleaned up: |
|---|
| 1176 | % for (i,j) <- usefulGen do (code using i and j) % |
|---|
| 1177 | This is possible using %map%, %filter%, and %nest%, but you end up |
|---|
| 1178 | effectively desugaring the code by hand. Using BIG GENERATOR is much easier. |
|---|
| 1179 | **) |
|---|
| 1180 | |
|---|
| 1181 | (** TODO |
|---|
| 1182 | |
|---|
| 1183 | The big problem here is that the new desugaring story actually gets in |
|---|
| 1184 | the way. We can't simply package up a function passed in, because |
|---|
| 1185 | that's being done by the __bigOperator functionality directly. |
|---|
| 1186 | |
|---|
| 1187 | How do we deal with reduction properties? It's all very sticky. And |
|---|
| 1188 | we're already running into difficulties with co- and contra-variance |
|---|
| 1189 | of the type parameters floating around that force us to use Any in |
|---|
| 1190 | awkward places. |
|---|
| 1191 | |
|---|
| 1192 | In particular, we don't want to generate the data when creating the |
|---|
| 1193 | generator, as that misses the whole point. We want to defer the |
|---|
| 1194 | object traversals until the moment the resulting generator is used. |
|---|
| 1195 | **) |
|---|
| 1196 | |
|---|
| 1197 | (************************************************************ |
|---|
| 1198 | * The Maybe type, used instead of null |
|---|
| 1199 | ************************************************************) |
|---|
| 1200 | |
|---|
| 1201 | (* This makes excludes work without where clauses, and allows opr =() |
|---|
| 1202 | to remain non-parametric. *) |
|---|
| 1203 | value trait AnyMaybe extends Equality[\AnyMaybe\] excludes Number |
|---|
| 1204 | (** \vspace{-4ex} NOT YET: %comprises Maybe[\T\] where [\T\]% *) |
|---|
| 1205 | getter holds() : Boolean |
|---|
| 1206 | opr =(self, other:AnyMaybe): Boolean = false |
|---|
| 1207 | end |
|---|
| 1208 | |
|---|
| 1209 | just(t:Any):AnyMaybe = Just(t) |
|---|
| 1210 | |
|---|
| 1211 | (** %Maybe% represents either %Nothing% or a single element of type |
|---|
| 1212 | %T% (%Just[\T\]%), which may be retrieved by calling %get%. An |
|---|
| 1213 | object of type %Maybe[\T\]% can be used as a generator; it is either |
|---|
| 1214 | empty (%Nothing%) or generates the single element yielded by |
|---|
| 1215 | %get%, so there is no issue of canonical order or parallelism. |
|---|
| 1216 | |
|---|
| 1217 | Thus, %Just[\T\]% can be used as a single-element generator, and |
|---|
| 1218 | %Nothing% can be used as an empty generator. *) |
|---|
| 1219 | value trait Maybe[\T\] |
|---|
| 1220 | extends { AnyMaybe, Condition[\T\] } |
|---|
| 1221 | comprises { Nothing[\T\], Just[\T\] } |
|---|
| 1222 | end |
|---|
| 1223 | |
|---|
| 1224 | value object Just[\T\](x:T) extends Maybe[\T\] |
|---|
| 1225 | getter size()=1 |
|---|
| 1226 | getter toString():String = "Just(" x ")" |
|---|
| 1227 | getter holds() = true |
|---|
| 1228 | getter get() = x |
|---|
| 1229 | opr |self| : ZZ32 = 1 |
|---|
| 1230 | getDefault(_:T): T = x |
|---|
| 1231 | cond[\R\](t:T->R, _:()->R): R = t(x) |
|---|
| 1232 | generate[\R\](_:Reduction[\R\],m:T->R): R = m(x) |
|---|
| 1233 | opr[i:ZZ32]:T = if i=0 then x else fail("Maybe[" i "] nonzero index") end |
|---|
| 1234 | |
|---|
| 1235 | map[\G\](f: T->G): Just[\G\] = Just[\G\](f(x)) |
|---|
| 1236 | cross[\G\](g: Generator[\G\]): Generator[\(T,G)\] = |
|---|
| 1237 | g.map[\(T,G)\](fn (e:G):(T,G) => (x,e)) |
|---|
| 1238 | |
|---|
| 1239 | mapReduce[\R\](m: T->R, _:(R,R)->R, _:R): R = m(x) |
|---|
| 1240 | reduce(_:(T,T)->T, _:T):T = x |
|---|
| 1241 | reduce(_: Reduction[\T\]):T = x |
|---|
| 1242 | loop(f:T->()): () = f(x) |
|---|
| 1243 | opr IN(y:T, self): Boolean = x=y |
|---|
| 1244 | opr =(self,o:Just[\T\]): Boolean = x=o.get |
|---|
| 1245 | end |
|---|
| 1246 | |
|---|
| 1247 | (* Obviously ought to be a non-parametric singleton when we get where |
|---|
| 1248 | clauses working. *) |
|---|
| 1249 | value object Nothing[\T\] extends Maybe[\T\] |
|---|
| 1250 | getter size()=0 |
|---|
| 1251 | getter holds() = false |
|---|
| 1252 | getter get() = throw NotFound |
|---|
| 1253 | getter toString():String = "Nothing" |
|---|
| 1254 | opr |self| : ZZ32 = 0 |
|---|
| 1255 | getDefault(t:T):T = t |
|---|
| 1256 | cond[\R\](_:T->R, e:()->R): R = e() |
|---|
| 1257 | generate[\R\](r:Reduction[\R\],_:T->R): R = r.empty() |
|---|
| 1258 | opr[_:ZZ32]: T = fail("Cannot index Nothing") |
|---|
| 1259 | |
|---|
| 1260 | map[\G\](f: T->G): Nothing[\G\] = Nothing[\G\] |
|---|
| 1261 | cross[\G\](g: Generator[\G\]): Generator[\(T,G)\] = Nothing[\(T,G)\] |
|---|
| 1262 | |
|---|
| 1263 | mapReduce[\R\](_: T->R, _:(R,R)->R, z:R): R = z |
|---|
| 1264 | reduce(_:(T,T)->T, z:T):T = z |
|---|
| 1265 | reduce(r: Reduction[\T\]):T = r.empty() |
|---|
| 1266 | loop(f:T->()): () = () |
|---|
| 1267 | opr IN(x:T, self): Boolean = false |
|---|
| 1268 | opr =(self,_:Nothing[\T\]) = true |
|---|
| 1269 | end |
|---|
| 1270 | |
|---|
| 1271 | (************************************************************ |
|---|
| 1272 | * Exception hierarchy |
|---|
| 1273 | ************************************************************) |
|---|
| 1274 | |
|---|
| 1275 | trait Exception comprises { UncheckedException, CheckedException } |
|---|
| 1276 | end |
|---|
| 1277 | |
|---|
| 1278 | (* Exceptions which are not checked *) |
|---|
| 1279 | |
|---|
| 1280 | trait UncheckedException extends Exception excludes CheckedException |
|---|
| 1281 | end |
|---|
| 1282 | |
|---|
| 1283 | object FailCalled(s:String) extends UncheckedException |
|---|
| 1284 | toString(): String = "FAIL: " s |
|---|
| 1285 | end |
|---|
| 1286 | |
|---|
| 1287 | object DivisionByZero extends UncheckedException |
|---|
| 1288 | toString(): String = "Division by zero" |
|---|
| 1289 | end |
|---|
| 1290 | |
|---|
| 1291 | object UnpastingError extends UncheckedException |
|---|
| 1292 | toString(): String = "Unpasting error" |
|---|
| 1293 | end |
|---|
| 1294 | |
|---|
| 1295 | object CallerViolation extends UncheckedException |
|---|
| 1296 | toString(): String = "Caller violation" |
|---|
| 1297 | end |
|---|
| 1298 | |
|---|
| 1299 | object CalleeViolation extends UncheckedException |
|---|
| 1300 | toString(): String = "Callee violation" |
|---|
| 1301 | end |
|---|
| 1302 | |
|---|
| 1303 | object TestFailure extends UncheckedException |
|---|
| 1304 | toString(): String = "Test failure" |
|---|
| 1305 | end |
|---|
| 1306 | |
|---|
| 1307 | object ContractHierarchyViolation extends UncheckedException |
|---|
| 1308 | toString(): String = "Contract hierarchy violation" |
|---|
| 1309 | end |
|---|
| 1310 | |
|---|
| 1311 | object NoEqualityOnFunctions extends UncheckedException |
|---|
| 1312 | toString(): String = "No equality on functions" |
|---|
| 1313 | end |
|---|
| 1314 | |
|---|
| 1315 | object InvalidRange extends UncheckedException |
|---|
| 1316 | toString(): String = "Invalid range" |
|---|
| 1317 | end |
|---|
| 1318 | |
|---|
| 1319 | object ForbiddenException(chain : Exception) extends UncheckedException |
|---|
| 1320 | toString(): String = "Forbidden exception" |
|---|
| 1321 | end |
|---|
| 1322 | |
|---|
| 1323 | (* Should this be called "IndexNotFound" instead? *) |
|---|
| 1324 | object NotFound extends UncheckedException |
|---|
| 1325 | toString(): String = "Not found" |
|---|
| 1326 | end |
|---|
| 1327 | |
|---|
| 1328 | object IndexOutOfBounds(min:ZZ32,max:ZZ32,index:ZZ32) extends UncheckedException |
|---|
| 1329 | toString(): String = index " is outside the range " min " to " max |
|---|
| 1330 | end |
|---|
| 1331 | |
|---|
| 1332 | object NegativeLength extends UncheckedException |
|---|
| 1333 | toString(): String = "Negative length" |
|---|
| 1334 | end |
|---|
| 1335 | |
|---|
| 1336 | object IntegerOverflow extends UncheckedException |
|---|
| 1337 | toString(): String = "Integer Overflow" |
|---|
| 1338 | end |
|---|
| 1339 | |
|---|
| 1340 | object RationalComparisonError extends UncheckedException |
|---|
| 1341 | toString(): String = "Rational comparison error" |
|---|
| 1342 | end |
|---|
| 1343 | |
|---|
| 1344 | object FloatingComparisonError extends UncheckedException |
|---|
| 1345 | toString(): String = "Floating comparison error" |
|---|
| 1346 | end |
|---|
| 1347 | |
|---|
| 1348 | (* Checked Exceptions *) |
|---|
| 1349 | |
|---|
| 1350 | trait CheckedException extends Exception excludes UncheckedException |
|---|
| 1351 | end |
|---|
| 1352 | |
|---|
| 1353 | object CastError extends CheckedException |
|---|
| 1354 | toString(): String = "Cast error" |
|---|
| 1355 | end |
|---|
| 1356 | |
|---|
| 1357 | object IOFailure extends CheckedException |
|---|
| 1358 | toString(): String = "I/O error" |
|---|
| 1359 | end |
|---|
| 1360 | |
|---|
| 1361 | object MatchFailure extends CheckedException |
|---|
| 1362 | toString(): String = "Match failure" |
|---|
| 1363 | end |
|---|
| 1364 | |
|---|
| 1365 | (* SetsNotDisjoint? *) |
|---|
| 1366 | object DisjointUnionError extends CheckedException |
|---|
| 1367 | toString(): String = "Disjoint union error" |
|---|
| 1368 | end |
|---|
| 1369 | |
|---|
| 1370 | object APIMissing extends CheckedException |
|---|
| 1371 | toString(): String = "Api is missing" |
|---|
| 1372 | end |
|---|
| 1373 | |
|---|
| 1374 | object APINameCollision extends CheckedException |
|---|
| 1375 | toString(): String = "Api name collides with another" |
|---|
| 1376 | end |
|---|
| 1377 | |
|---|
| 1378 | object ExportedAPIMissing extends CheckedException |
|---|
| 1379 | toString(): String = "Exported api is missing" |
|---|
| 1380 | end |
|---|
| 1381 | |
|---|
| 1382 | object HiddenAPIMissing extends CheckedException |
|---|
| 1383 | toString(): String = "Hidden api is missing" |
|---|
| 1384 | end |
|---|
| 1385 | |
|---|
| 1386 | object TryAtomicFailure extends CheckedException |
|---|
| 1387 | toString(): String = "Try/atomic failure" |
|---|
| 1388 | end |
|---|
| 1389 | |
|---|
| 1390 | (* Should take a spawned thread as an argument *) |
|---|
| 1391 | object AtomicSpawnSynchronization extends {UncheckedException} |
|---|
| 1392 | toString(): String = "Atomic spawn synchronization" |
|---|
| 1393 | end |
|---|
| 1394 | |
|---|
| 1395 | (************************************************************ |
|---|
| 1396 | * Array support |
|---|
| 1397 | ************************************************************) |
|---|
| 1398 | |
|---|
| 1399 | oops(s:ZZ32, l:ZZ32, sz:ZZ32, got:ZZ32):() = do |
|---|
| 1400 | fail("Index of dimension " s " out of bounds; got " got |
|---|
| 1401 | " which is not in " l "#" sz); |
|---|
| 1402 | end |
|---|
| 1403 | |
|---|
| 1404 | trait HasRank extends Equality[\HasRank\] excludes { Number, AnyMaybe } |
|---|
| 1405 | (** \vspace{-4ex} NOT YET: %comprises Array[\T,E,I\] |
|---|
| 1406 | where [\T,E,I\]{ T extends Array[\T,E,I\] }% *) |
|---|
| 1407 | rank():ZZ32 |
|---|
| 1408 | opr =(self, other:HasRank): Boolean = false |
|---|
| 1409 | end |
|---|
| 1410 | |
|---|
| 1411 | (* Declared Rank-n-ness *) |
|---|
| 1412 | trait Rank[\ nat n \] extends HasRank |
|---|
| 1413 | rank():ZZ32 = n |
|---|
| 1414 | end |
|---|
| 1415 | |
|---|
| 1416 | (* Potemkin exclusion traits. Really we just want to say that |
|---|
| 1417 | * Rank[\n\] excludes Rank[\m\] where { m =/= n }, but we can't yet. *) |
|---|
| 1418 | |
|---|
| 1419 | trait Rank1 extends { Rank[\1\]} excludes { Rank2, Rank3, Number, String } |
|---|
| 1420 | end |
|---|
| 1421 | |
|---|
| 1422 | trait Rank2 extends { Rank[\2\]} excludes { Rank3, Number, String } |
|---|
| 1423 | end |
|---|
| 1424 | |
|---|
| 1425 | trait Rank3 extends { Rank[\3\]} excludes { Number, String } |
|---|
| 1426 | end |
|---|
| 1427 | |
|---|
| 1428 | (* The trait Indexed_i[\n\] indicates that something has an i^th |
|---|
| 1429 | * dimension of size n. In general anything which extends Indexed_i |
|---|
| 1430 | * must also extend Indexed_j for j < i. *) |
|---|
| 1431 | |
|---|
| 1432 | trait Indexed1[\ nat n \] extends HasRank end |
|---|
| 1433 | |
|---|
| 1434 | trait Indexed2[\ nat n \] extends HasRank end |
|---|
| 1435 | |
|---|
| 1436 | trait Indexed3[\ nat n \] extends HasRank end |
|---|
| 1437 | |
|---|
| 1438 | (** The indexed trait indicates that an object of type T can be |
|---|
| 1439 | indexed using type I to obtain elements with type E. |
|---|
| 1440 | |
|---|
| 1441 | An object i that's an instance of Indexed defines three basic things: |
|---|
| 1442 | The indexing operator opr [], which must be defined for every instance of |
|---|
| 1443 | the type. |
|---|
| 1444 | |
|---|
| 1445 | A suite of generators: i.indices generates the index space of the |
|---|
| 1446 | array. i itself generates the values contained at those indices. |
|---|
| 1447 | i.indexValuePairs yields pairs of (index,value). All of these |
|---|
| 1448 | share the same natural order. It is necessary to define one of |
|---|
| 1449 | indices() and indexValuePairs(), in addition to generate() (but |
|---|
| 1450 | the latter requirement can be dispensed by instead extending |
|---|
| 1451 | DelegatedIndexed). |
|---|
| 1452 | |
|---|
| 1453 | A set of utility functions, assign, fill, and copy. Only fill and |
|---|
| 1454 | copy need to be defined. |
|---|
| 1455 | **) |
|---|
| 1456 | trait Indexed[\E, I\] extends Generator[\E\] |
|---|
| 1457 | (** isEmpty indicates whether there are any valid indices. It is |
|---|
| 1458 | defined as size=0 *) |
|---|
| 1459 | getter isEmpty(): Boolean = |self| = 0 |
|---|
| 1460 | getter nonEmpty(): Boolean = NOT self.isEmpty |
|---|
| 1461 | (** %self.size% is equivalent to %|self|%. *) |
|---|
| 1462 | getter size(): ZZ32 |
|---|
| 1463 | (** bounds() yields a range of indices that are valid for the |
|---|
| 1464 | indexed generator. *) |
|---|
| 1465 | getter bounds(): FullRange[\I,true\] |
|---|
| 1466 | (** indexValuePairs() generates the elements of the indexed object |
|---|
| 1467 | (exactly those elements that are generated by the object itself), |
|---|
| 1468 | but each element is paired with its index. When we obtain |
|---|
| 1469 | (i,v) from indexValuePairs we know that: |
|---|
| 1470 | self[i] = v |
|---|
| 1471 | the i are distinct and i IN bounds() |
|---|
| 1472 | stripping away the i yields exactly the results of v <- self |
|---|
| 1473 | This generator attempts to follow the structure of the |
|---|
| 1474 | underlying object as closely as possible. *) |
|---|
| 1475 | getter indexValuePairs(): Indexed[\(I,E),I\] = |
|---|
| 1476 | indices().map[\(I,E)\](fn (i:I): (I,E) => (i,self[i])) |
|---|
| 1477 | (** indices() yields the indices corresponding to the elements of |
|---|
| 1478 | the indexed object---it corresponds to the index component of |
|---|
| 1479 | indexValuePairs(). This may in general be a subset of all the |
|---|
| 1480 | valid indices represented by bounds(). This generator |
|---|
| 1481 | attempts to follow the structure of the underlying object as |
|---|
| 1482 | closely as possible. *) |
|---|
| 1483 | getter indices(): Indexed[\I,I\] = |
|---|
| 1484 | indexValuePairs().map[\I\](fn (i:I, e:E): I => i) |
|---|
| 1485 | |
|---|
| 1486 | (** %|self|% indicates the number of distinct valid indices that may |
|---|
| 1487 | be passed to indexing operations. *) |
|---|
| 1488 | opr |self| : ZZ32 |
|---|
| 1489 | |
|---|
| 1490 | (** Indexing. i IN bounds() must hold. *) |
|---|
| 1491 | opr[i:I] : E |
|---|
| 1492 | |
|---|
| 1493 | (** Locality of a particular index (NOT of its contents!). *) |
|---|
| 1494 | region(i:I): Region = Global |
|---|
| 1495 | |
|---|
| 1496 | (** Indexing by ranges. The results are 0-based when the |
|---|
| 1497 | underlying index type has a notion of 0. This ensures |
|---|
| 1498 | consistency of behavior between types such as vectors that |
|---|
| 1499 | *only* support 0 indexing and types such as arrays that permit |
|---|
| 1500 | other choices of lower bounds. The easiest way to write the |
|---|
| 1501 | index by ranges operation for an instance of Indexed is to |
|---|
| 1502 | take advantage of indexing on the ranges themselves by writing |
|---|
| 1503 | (bounds())[r] in order to narrow and bounds check the range r |
|---|
| 1504 | and obtain a closed range of indices on the underlying |
|---|
| 1505 | data. **) |
|---|
| 1506 | opr[r:Range[\I\]] : Indexed[\E,I\] |
|---|
| 1507 | opr[_:OpenRange[\Any\]] : Indexed[\E,I\] = self[OpenRange[\I\]] |
|---|
| 1508 | |
|---|
| 1509 | (** Roughly speaking, ivmap(f) is equivalent to |
|---|
| 1510 | indexValuePairs.map(f). However ivmap function isn't merely a |
|---|
| 1511 | convenient shortcut. It's actually intended to create a copy |
|---|
| 1512 | of the underlying indexed structure when that is appropriate. |
|---|
| 1513 | |
|---|
| 1514 | The usual map function in Generator should do the same (and |
|---|
| 1515 | does for the instances in this library). Copying can be bad |
|---|
| 1516 | for space, but is complexity-preserving if the mapped |
|---|
| 1517 | generator is used more than once. **) |
|---|
| 1518 | ivmap[\R\](f:(I,E)->R): Indexed[\R, I\] = indexValuePairs().map[\R\](f) |
|---|
| 1519 | map[\R\](f:E->R): Indexed[\R, I\] = SimpleMappedIndexed[\E,R,I\](self,f) |
|---|
| 1520 | |
|---|
| 1521 | (** indexOf(e) returns an index at which e can be found, |
|---|
| 1522 | or Nothing if no such index exists. **) |
|---|
| 1523 | indexOf(e:E): Maybe[\I\] = |
|---|
| 1524 | label found |
|---|
| 1525 | for (i,v) <- indexValuePairs(), v=e do |
|---|
| 1526 | exit found with Just[\I\](i) |
|---|
| 1527 | end |
|---|
| 1528 | Nothing[\I\] |
|---|
| 1529 | end found |
|---|
| 1530 | end |
|---|
| 1531 | |
|---|
| 1532 | trait ZeroIndexed[\E\] extends Indexed[\E,ZZ32\] |
|---|
| 1533 | bounds(): FullRange[\ZZ32,true\] = 0 # |self| |
|---|
| 1534 | zip[\F\](g:ZeroIndexed[\F\]):ZeroIndexed[\(E,F)\] = |
|---|
| 1535 | DefaultZip[\E,F\](self,g) |
|---|
| 1536 | end |
|---|
| 1537 | |
|---|
| 1538 | object DefaultZip[\E,F\](e:ZeroIndexed[\E\],f:ZeroIndexed[\F\]) |
|---|
| 1539 | extends { ZeroIndexed[\(E,F)\], DelegatedIndexed[\(E,F),ZZ32\] } |
|---|
| 1540 | getter size(): ZZ32 = |self| |
|---|
| 1541 | getter indices(): Generator[\ZZ32\] = |
|---|
| 1542 | if |e| <= |f| then e.indices else f.indices end |
|---|
| 1543 | opr |self| : ZZ32 = |e| MIN |f| |
|---|
| 1544 | opr[i:ZZ32]:(E,F) = (e[i],f[i]) |
|---|
| 1545 | opr[r:Range[\ZZ32\]] : ZeroIndexed[\(E,F)\] = |
|---|
| 1546 | DefaultZip[\E,F\](e[r],f[r]) |
|---|
| 1547 | end |
|---|
| 1548 | |
|---|
| 1549 | trait LexicographicOrder[\T extends LexicographicOrder[\T,E\],E\] |
|---|
| 1550 | extends { StandardTotalOrder[\T\], ZeroIndexed[\E\] } |
|---|
| 1551 | opr CMP(self, other:T): TotalComparison = |
|---|
| 1552 | self.zip[\E\](other).generate[\TotalComparison\]( |
|---|
| 1553 | LexicographicReduction, |
|---|
| 1554 | fn(a:E,b:E): TotalComparison => a CMP b) LEXICO |
|---|
| 1555 | (|self| CMP |other|) |
|---|
| 1556 | (** We give a specialized version of = because it can fail faster |
|---|
| 1557 | than CMP by checking sizes early. **) |
|---|
| 1558 | opr =(self,other:T): Boolean = |
|---|
| 1559 | (|self| = |other|) AND: |
|---|
| 1560 | (BIG AND [(a,b)<-self.zip[\E\](other)] a=b) |
|---|
| 1561 | end |
|---|
| 1562 | |
|---|
| 1563 | toArray[\E\](g:Indexed[\E,ZZ32\]): Array[\E,ZZ32\] = do |
|---|
| 1564 | bnds = g.bounds |
|---|
| 1565 | r = array[\E\](|bnds|).shift(bnds.lower()) |
|---|
| 1566 | for (i,v) <- g.indexValuePairs do |
|---|
| 1567 | r.init(i,v) |
|---|
| 1568 | end |
|---|
| 1569 | r |
|---|
| 1570 | end |
|---|
| 1571 | |
|---|
| 1572 | (** DelegatedIndexed is an Indexed generator that has recourse to |
|---|
| 1573 | another Indexed generator() internally. By default this in turn |
|---|
| 1574 | is defined in terms of indexValuePairs(). Thus it's only |
|---|
| 1575 | necessary to define either indexValuePairs() or indices(). |
|---|
| 1576 | |
|---|
| 1577 | This class is designed for convenience; it shouldn't be used as a |
|---|
| 1578 | type in runing code, but only as a supertype in lieu of Indexed. |
|---|
| 1579 | **) |
|---|
| 1580 | trait DelegatedIndexed[\E,I\] extends Indexed[\E,I\] |
|---|
| 1581 | getter generator(): Generator[\E\] = |
|---|
| 1582 | indexValuePairs().map[\E\](fn (i:I, e:E): E => e) |
|---|
| 1583 | getter size(): ZZ32 = |generator()| |
|---|
| 1584 | opr |self| : ZZ32 = |generator()| |
|---|
| 1585 | generate[\R\](r: Reduction[\R\], body: E->R): R = |
|---|
| 1586 | generator().generate[\R\](r,body) |
|---|
| 1587 | seq(self): SequentialGenerator[\E\] = seq(generator()) |
|---|
| 1588 | cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] = |
|---|
| 1589 | generator().cross[\G\](g) |
|---|
| 1590 | mapReduce[\R\](body: E->R, join:(R,R)->R, id:R): R = |
|---|
| 1591 | generator().mapReduce[\R\](body,join,id) |
|---|
| 1592 | reduce(j:(E,E)->E, z:E):E = generator().reduce(j,z) |
|---|
| 1593 | reduce(r: Reduction[\E\]):E = generator().reduce(r) |
|---|
| 1594 | loop(f:E->()): () = generator().loop(f) |
|---|
| 1595 | end |
|---|
| 1596 | |
|---|
| 1597 | (** The MutableIndexed trait is an indexed trait whose elements can be |
|---|
| 1598 | mutated using indexed assignment. Right now we're using this type |
|---|
| 1599 | in a somewhat dangerous way, since eg Array1[\E,b0,s0\] extends |
|---|
| 1600 | both Indexed[\Array1[\E,b0,s0\],E,ZZ32\] and |
|---|
| 1601 | Indexed[\Array[\E,ZZ32\],E,ZZ32\]. We will need to find a |
|---|
| 1602 | solution to this at some point. |
|---|
| 1603 | **) |
|---|
| 1604 | trait MutableIndexed[\E, I\] |
|---|
| 1605 | extends { Indexed[\E,I\] } |
|---|
| 1606 | opr[i:I]:=(v:E) : () |
|---|
| 1607 | |
|---|
| 1608 | (** For Ranged assignment, the extents of r and v.bounds must |
|---|
| 1609 | match, but the lower bounds need not. **) |
|---|
| 1610 | opr[r:Range[\I\]]:=(v:Indexed[\E,I\]) : () |
|---|
| 1611 | opr[_:OpenRange[\Any\]]:=(v:Indexed[\E,I\]) : () = |
|---|
| 1612 | do self[bounds()] := v end |
|---|
| 1613 | end |
|---|
| 1614 | |
|---|
| 1615 | (* Array whose bounds are implicit rather than static, and which may |
|---|
| 1616 | be either mutable or immutable. *) |
|---|
| 1617 | trait ReadableArray[\E,I\] |
|---|
| 1618 | extends { HasRank, Indexed[\E,I\], DelegatedIndexed[\E,I\] } |
|---|
| 1619 | comprises { Array[\E,I\], ImmutableArray[\E,I\] } |
|---|
| 1620 | (** CONCRETE GETTERS |
|---|
| 1621 | Default implementations of getters based on abstract methods |
|---|
| 1622 | below. **) |
|---|
| 1623 | getter indices(): Indexed[\I,I\] = bounds() |
|---|
| 1624 | getter indexValuePairs(): Indexed[\(I,E),I\] = |
|---|
| 1625 | zeroIndices().map[\(I,E)\](fn (i:I):(I,E) => (toIndex(i),get(i))) |
|---|
| 1626 | getter generator(): Indexed[\E,I\] = |
|---|
| 1627 | zeroIndices().map[\E\](fn (i:I):E => get(i)) |
|---|
| 1628 | |
|---|
| 1629 | (** CONCRETE METHODS |
|---|
| 1630 | Default implementations of most array stuff based on the above. |
|---|
| 1631 | The things we can't provide are anything involving replica. **) |
|---|
| 1632 | |
|---|
| 1633 | opr[i:I]:E = get(offset(i)) |
|---|
| 1634 | |
|---|
| 1635 | (** Initialize element at index i with value v. This should occur |
|---|
| 1636 | once, before any other access or assignment occurs to element |
|---|
| 1637 | i. An error will be signaled if an uninitialized element is |
|---|
| 1638 | read or an initialized element is re-initialized. **) |
|---|
| 1639 | init(i:I, v:E) = init0(offset(i),v) |
|---|
| 1640 | |
|---|
| 1641 | generate[\R\](r: Reduction[\R\], body: E->R): R = |
|---|
| 1642 | generator().generate[\R\](r,body) |
|---|
| 1643 | seq(self): SequentialGenerator[\E\] = seq(generator()) |
|---|
| 1644 | |
|---|
| 1645 | (** 0-based non-bounds-checked indexing **) |
|---|
| 1646 | get(i:I): E |
|---|
| 1647 | init0(i:I, e:E): () |
|---|
| 1648 | zeroIndices(): FullRange[\I,true\] |
|---|
| 1649 | (** Convert from base()-based indexing to 0-based indexing, |
|---|
| 1650 | performing bounds checking. **) |
|---|
| 1651 | offset(i:I): I |
|---|
| 1652 | (** Convert from 0-based indexing to base()-based indexing **) |
|---|
| 1653 | toIndex(i:I): I |
|---|
| 1654 | |
|---|
| 1655 | (** Indexed functionality with more specific type information **) |
|---|
| 1656 | opr[r:Range[\I\]] : ReadableArray[\E,I\] |
|---|
| 1657 | opr[_:OpenRange[\Any\]] : ReadableArray[\E,I\] |
|---|
| 1658 | ivmap[\R\](f:(I,E)->R): ReadableArray[\R, I\] |
|---|
| 1659 | map[\R\](f:E->R): ReadableArray[\R, I\] |
|---|
| 1660 | |
|---|
| 1661 | (** Shift the origin of an array. This should yield a new view of |
|---|
| 1662 | the same array; ie initialization and/or update to either will |
|---|
| 1663 | be reflected in the other. **) |
|---|
| 1664 | shift(newOrigin:I):ReadableArray[\E,I\] |
|---|
| 1665 | |
|---|
| 1666 | (** Bulk initialization of an array using a given function or |
|---|
| 1667 | value. These are defined with more specific self types in |
|---|
| 1668 | StandardImmutableArrayType. **) |
|---|
| 1669 | fill(f:I->E):ReadableArray[\E,I\] |
|---|
| 1670 | fill(v:E):ReadableArray[\E,I\] |
|---|
| 1671 | |
|---|
| 1672 | copy():ReadableArray[\E,I\] |
|---|
| 1673 | |
|---|
| 1674 | (** Create a fresh array structurally identical to the present |
|---|
| 1675 | one, but holding elements of type U. **) |
|---|
| 1676 | replica[\U\]():ReadableArray[\U,I\] |
|---|
| 1677 | |
|---|
| 1678 | opr =(self, other:HasRank): Boolean = |
|---|
| 1679 | typecase other of |
|---|
| 1680 | ReadableArray[\E,I\] => indices().generate[\Boolean\](AndReduction, |
|---|
| 1681 | fn (i:I):Boolean => (self[i]=other[i])) |
|---|
| 1682 | else => false |
|---|
| 1683 | end |
|---|
| 1684 | |
|---|
| 1685 | end |
|---|
| 1686 | |
|---|
| 1687 | trait ImmutableArray[\E,I\] extends { ReadableArray[\E,I\] } |
|---|
| 1688 | excludes { Array[\E,I\] } |
|---|
| 1689 | opr[r:Range[\I\]] : ImmutableArray[\E,I\] |
|---|
| 1690 | opr[_:OpenRange[\Any\]] : ImmutableArray[\E,I\] |
|---|
| 1691 | ivmap[\R\](f:(I,E)->R): ImmutableArray[\R, I\] |
|---|
| 1692 | map[\R\](f:E->R): ImmutableArray[\R, I\] |
|---|
| 1693 | shift(newOrigin:I):ImmutableArray[\E,I\] |
|---|
| 1694 | fill(f:I->E):ImmutableArray[\E,I\] |
|---|
| 1695 | fill(v:E):ImmutableArray[\E,I\] |
|---|
| 1696 | copy():ImmutableArray[\E,I\] |
|---|
| 1697 | replica[\U\]():ImmutableArray[\U,I\] |
|---|
| 1698 | |
|---|
| 1699 | (** Thaw array (return mutable copy) **) |
|---|
| 1700 | thaw():Array[\E,I\] |
|---|
| 1701 | end |
|---|
| 1702 | |
|---|
| 1703 | trait Array[\E,I\] extends { ReadableArray[\E,I\], MutableIndexed[\E,I\] } |
|---|
| 1704 | (** 0-based non-bounds-checked indexing **) |
|---|
| 1705 | put(i:I, e:E): () |
|---|
| 1706 | opr[i:I]:=(v:E):() = put(offset(i),v) |
|---|
| 1707 | |
|---|
| 1708 | opr[r:Range[\I\]]:=(a:Indexed[\E,I\]):() = do |
|---|
| 1709 | a0 = a[a.bounds] (* Make a have 0 origin *) |
|---|
| 1710 | s0 = self[r] (* Make self have 0 origin *) |
|---|
| 1711 | if a0.bounds = s0.bounds then |
|---|
| 1712 | for (i,v) <- a0.indexValuePairs do |
|---|
| 1713 | s0.put(i,v) |
|---|
| 1714 | end |
|---|
| 1715 | else |
|---|
| 1716 | fail("Can't assign indexed with bounds " a.bounds // |
|---|
| 1717 | " to differently-sized subarray " self.bounds) |
|---|
| 1718 | end |
|---|
| 1719 | end |
|---|
| 1720 | |
|---|
| 1721 | (** The following are repetition with better return type info. **) |
|---|
| 1722 | opr[r:Range[\I\]] : Array[\E,I\] |
|---|
| 1723 | opr[_:OpenRange[\Any\]] : Array[\E,I\] |
|---|
| 1724 | ivmap[\R\](f:(I,E)->R): Array[\R, I\] |
|---|
| 1725 | map[\R\](f:E->R): Array[\R, I\] |
|---|
| 1726 | shift(newOrigin:I):Array[\E,I\] |
|---|
| 1727 | fill(f:I->E):Array[\E,I\] |
|---|
| 1728 | fill(v:E):Array[\E,I\] |
|---|
| 1729 | assign(f:I->E):Array[\E,I\] |
|---|
| 1730 | copy():Array[\E,I\] |
|---|
| 1731 | replica[\U\]():Array[\U,I\] |
|---|
| 1732 | |
|---|
| 1733 | (** Freeze array (return mutable copy) **) |
|---|
| 1734 | freeze(): ImmutableArray[\E,I\] |
|---|
| 1735 | end |
|---|
| 1736 | |
|---|
| 1737 | (** Factory for arrays that returns an empty 0-indexed array of a given |
|---|
| 1738 | run-time-determined size. **) |
|---|
| 1739 | array[\E\](x:ZZ32):Array[\E,ZZ32\] = __arr1(__Proxy[\E\],reflect(x)) |
|---|
| 1740 | array[\E\](x:ZZ32,y:ZZ32):Array[\E,(ZZ32,ZZ32)\] = |
|---|
| 1741 | __arr2(__Proxy[\E\],reflect(x), reflect(y)) |
|---|
| 1742 | array[\E\](x:ZZ32,y:ZZ32,z:ZZ32):Array[\E,(ZZ32,ZZ32,ZZ32)\] = |
|---|
| 1743 | __arr3(__Proxy[\E\],reflect(x), reflect(y), reflect(z)) |
|---|
| 1744 | |
|---|
| 1745 | (* This should be local to array, but we don't support local |
|---|
| 1746 | parametric methods in the language spec at all at the moment. *) |
|---|
| 1747 | __arr1[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):Array1[\E,0,n\] = |
|---|
| 1748 | array1[\E,n\]() |
|---|
| 1749 | __arr2[\E, nat n, nat m\](w:__Proxy[\E\],x:N[\n\],y:N[\m\]): |
|---|
| 1750 | Array2[\E,0,n,0,m\] = array2[\E,n,m\]() |
|---|
| 1751 | __arr3[\E, nat n, nat m, nat p\](w:__Proxy[\E\],x:N[\n\],y:N[\m\],z:N[\p\]): |
|---|
| 1752 | Array3[\E,0,n,0,m,0,p\] = array3[\E,n,m,p\]() |
|---|
| 1753 | |
|---|
| 1754 | (** Factory for immutable arrays that returns an empty 0-indexed array |
|---|
| 1755 | of a given run-time-determined size. **) |
|---|
| 1756 | immutableArray[\E\](x:ZZ32):ImmutableArray[\E,ZZ32\] = |
|---|
| 1757 | __imm1(__Proxy[\E\],reflect(x)) |
|---|
| 1758 | (* |
|---|
| 1759 | immutableArray[\E\](x:ZZ32,y:ZZ32):ImmutableArray[\E,(ZZ32,ZZ32)\] = |
|---|
| 1760 | __imm2(__Proxy[\E\],reflect(x), reflect(y)) |
|---|
| 1761 | immutableArray[\E\](x:ZZ32,y:ZZ32,z:ZZ32):ImmutableArray[\E,(ZZ32,ZZ32,ZZ32)\] = |
|---|
| 1762 | __imm3(__Proxy[\E\],reflect(x), reflect(y), reflect(z)) |
|---|
| 1763 | *) |
|---|
| 1764 | |
|---|
| 1765 | (* This should be local to immutableArray, but we don't support local |
|---|
| 1766 | parametric methods in the language spec at all at the moment. *) |
|---|
| 1767 | __imm1[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):ImmutableArray1[\E,0,n\] = |
|---|
| 1768 | immutableArray1[\E,n\]() |
|---|
| 1769 | (* |
|---|
| 1770 | __imm2[\E, nat n, nat m\](w:__Proxy[\E\],x:N[\n\],y:N[\m\]): |
|---|
| 1771 | ImmutableArray2[\E,0,n,0,m\] = immutableArray2[\E,n,m\]() |
|---|
| 1772 | __imm3[\E, nat n, nat m, nat p\](w:__Proxy[\E\],x:N[\n\],y:N[\m\],z:N[\p\]): |
|---|
| 1773 | ImmutableArray3[\E,0,n,0,m,0,p\] = immutableArray3[\E,n,m,p\]() |
|---|
| 1774 | *) |
|---|
| 1775 | |
|---|
| 1776 | primitiveArray[\E\](x:ZZ32):Array[\E,ZZ32\] = __parr(__Proxy[\E\],reflect(x)) |
|---|
| 1777 | __parr[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):PrimitiveArray[\E,n\] = |
|---|
| 1778 | PrimitiveArray[\E,n\]() |
|---|
| 1779 | |
|---|
| 1780 | primitiveImmutableArray[\E\](x:ZZ32):ImmutableArray[\E,ZZ32\] = |
|---|
| 1781 | __piarr(__Proxy[\E\],reflect(x)) |
|---|
| 1782 | __piarr[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):PrimImmutableArray[\E,n\] = |
|---|
| 1783 | PrimImmutableArray[\E,n\]() |
|---|
| 1784 | |
|---|
| 1785 | (** NOTE: StandardImmutableArrayType is a parent of |
|---|
| 1786 | StandardMutableArrayType. It therefore doesn't extend |
|---|
| 1787 | ImmutableArray as you might expect. Other types that extend |
|---|
| 1788 | it should also extend ImmutableArray explicitly. **) |
|---|
| 1789 | trait StandardImmutableArrayType[\T extends StandardImmutableArrayType[\T,E,I\],E,I\] |
|---|
| 1790 | extends { ReadableArray[\E,I\] } |
|---|
| 1791 | fill(f:I->E):T = do |
|---|
| 1792 | for i <- zeroIndices() do init0(i,f(toIndex(i))) end |
|---|
| 1793 | self |
|---|
| 1794 | end |
|---|
| 1795 | fill(v:E):T = do |
|---|
| 1796 | for i <- zeroIndices() do init0(i,v) end |
|---|
| 1797 | self |
|---|
| 1798 | end |
|---|
| 1799 | |
|---|
| 1800 | copy():T |
|---|
| 1801 | end |
|---|
| 1802 | |
|---|
| 1803 | |
|---|
| 1804 | trait StandardMutableArrayType[\T extends StandardMutableArrayType[\T,E,I\],E,I\] |
|---|
| 1805 | extends { StandardImmutableArrayType[\T,E,I\], Array[\E,I\] } |
|---|
| 1806 | assign(v:T):T = do |
|---|
| 1807 | for i <- zeroIndices() do put(i,v.get(i)) end |
|---|
| 1808 | self |
|---|
| 1809 | end |
|---|
| 1810 | assign(f:I->E):T = do |
|---|
| 1811 | for i <- zeroIndices() do put(i,f(toIndex(i))) end |
|---|
| 1812 | self |
|---|
| 1813 | end |
|---|
| 1814 | end |
|---|
| 1815 | |
|---|
| 1816 | (* Canonical partitioning of a positive number x into two pieces. If |
|---|
| 1817 | (a,b) = partition(n) |
|---|
| 1818 | and n > 0 then 0 < a <= b, n = a + b. |
|---|
| 1819 | As it turns out we choose a to be the largest power of 2 < n. |
|---|
| 1820 | *) |
|---|
| 1821 | partition(x:ZZ32):(ZZ32,ZZ32) = do |
|---|
| 1822 | m = partitionL(x) |
|---|
| 1823 | (m,x-m) |
|---|
| 1824 | end |
|---|
| 1825 | |
|---|
| 1826 | (** A ReadableArray1[\T,b0,s0\] is an arbitrary 1-dimensional array |
|---|
| 1827 | whose s0 elements are of type T, and whose lowest index is b0. |
|---|
| 1828 | |
|---|
| 1829 | The natural order of all generators is from b0 to b0+s0-1. **) |
|---|
| 1830 | trait ReadableArray1[\T, nat b0, nat s0\] |
|---|
| 1831 | extends { Indexed1[\s0\], Rank1, ReadableArray[\T,ZZ32\] } |
|---|
| 1832 | comprises { ImmutableArray1[\T,b0,s0\], Array1[\T,b0,s0\] } |
|---|
| 1833 | getter size():ZZ32 = s0 |
|---|
| 1834 | getter bounds():ScalarRange[\ZZ32,true\] = ParRange[\ZZ32,true\](b0,s0) |
|---|
| 1835 | getter mutability():String |
|---|
| 1836 | getter toString() = do |
|---|
| 1837 | r = "[" b0 "#" s0 "]" mutability() " = [" |
|---|
| 1838 | if s0=0 then |
|---|
| 1839 | r "]" |
|---|
| 1840 | else |
|---|
| 1841 | f(i:ZZ32,t:T):String = " " t |
|---|
| 1842 | j(a:String,b:String):String = a b |
|---|
| 1843 | r indexValuePairs().mapReduce[\String\](f,j,"") " ]" |
|---|
| 1844 | end |
|---|
| 1845 | end |
|---|
| 1846 | |
|---|
| 1847 | opr |self| : ZZ32 = s0 |
|---|
| 1848 | |
|---|
| 1849 | subarray[\nat b, nat s, nat o\]():ReadableArray1[\T, b, s\] |
|---|
| 1850 | |
|---|
| 1851 | (* Offset converts from b0 indexing to 0 indexing, |
|---|
| 1852 | bounds checking en route *) |
|---|
| 1853 | offset(i:ZZ32):ZZ32 = do |
|---|
| 1854 | r = i - b0 |
|---|
| 1855 | if NOT (0 <= r < s0) then oops(1, b0, s0, i) end |
|---|
| 1856 | r |
|---|
| 1857 | end |
|---|
| 1858 | toIndex(i:ZZ32):ZZ32 = i + b0 |
|---|
| 1859 | |
|---|
| 1860 | zeroIndices(): ScalarRange[\ZZ32,true\] = ParRange[\ZZ32,true\](0,s0) |
|---|
| 1861 | end |
|---|
| 1862 | |
|---|
| 1863 | trait ImmutableArray1[\T, nat b0, nat s0\] |
|---|
| 1864 | extends { StandardImmutableArrayType[\ImmutableArray1[\T,b0,s0\],T,ZZ32\], |
|---|
| 1865 | ImmutableArray[\T,ZZ32\], ReadableArray1[\T,b0,s0\] } |
|---|
| 1866 | getter mutability():String = "(immutable)" |
|---|
| 1867 | shift(o:ZZ32): ImmutableArray[\T,ZZ32\] = |
|---|
| 1868 | if o=0 then |
|---|
| 1869 | self |
|---|
| 1870 | else |
|---|
| 1871 | __subarrayI(self,reflect(o),N[\s0\],N[\b0\]) |
|---|
| 1872 | end |
|---|
| 1873 | |
|---|
| 1874 | opr[r: Range[\ZZ32\]] : ImmutableArray[\T,ZZ32\] = do |
|---|
| 1875 | r' = (bounds())[r] |
|---|
| 1876 | z = N[\0\] |
|---|
| 1877 | s = reflect( |r'| ) |
|---|
| 1878 | l = reflect(r'.lower()) |
|---|
| 1879 | __subarrayI(self,z,s,l) |
|---|
| 1880 | end |
|---|
| 1881 | opr[_:OpenRange[\ZZ32\]] : ImmutableArray1[\T,0,s0\] = |
|---|
| 1882 | subarray[\0,s0,0\]() |
|---|
| 1883 | opr[_:OpenRange[\Any\]] : ImmutableArray1[\T,0,s0\] = |
|---|
| 1884 | subarray[\0,s0,0\]() |
|---|
| 1885 | |
|---|
| 1886 | (** subarray selects a subarray of this array based on static parameters. |
|---|
| 1887 | b#s are the new bounds of the array; o is |
|---|
| 1888 | the index of the subarray within the current array. **) |
|---|
| 1889 | subarray[\nat b, nat s, nat o\]():ImmutableArray1[\T, b, s\] = do |
|---|
| 1890 | boundsCheck = (bounds())[o#s] |
|---|
| 1891 | __ImmutableSubArray1[\T,b,s,b0,s0\](self,o-b0,1) |
|---|
| 1892 | end |
|---|
| 1893 | |
|---|
| 1894 | (* the replica method returns a replica of the array (similar layout |
|---|
| 1895 | etc.) but with a different element type. *) |
|---|
| 1896 | replica[\U\]():ImmutableArray1[\U,b0,s0\] = __immutableFactory1[\U,b0,s0\]() |
|---|
| 1897 | |
|---|
| 1898 | copy():ImmutableArray1[\T,b0,s0\] = |
|---|
| 1899 | replica[\T\]().fill(fn (i:ZZ32):T => get(i-b0)) |
|---|
| 1900 | |
|---|
| 1901 | thaw():Array1[\T,b0,s0\] = |
|---|
| 1902 | __builtinFactory1[\T,b0,s0\]().fill(fn (i:ZZ32):T => get(i-b0)) |
|---|
| 1903 | |
|---|
| 1904 | map[\R\](f:T->R): ImmutableArray1[\R,b0,s0\] = |
|---|
| 1905 | replica[\R\]().fill(fn (i:ZZ32):R => f(get(i-b0))) |
|---|
| 1906 | ivmap[\R\](f:(ZZ32,T)->R): ImmutableArray1[\R,b0,s0\] = |
|---|
| 1907 | replica[\R\]().fill(fn (i:ZZ32):R => f(i,get(i-b0))) |
|---|
| 1908 | end |
|---|
| 1909 | |
|---|
| 1910 | (** Array1[\T,b0,s0\] is a 1-dimension array whose s0 elements are of |
|---|
| 1911 | type T, and whose lowest index is b0. **) |
|---|
| 1912 | trait Array1[\T, nat b0, nat s0\] |
|---|
| 1913 | extends { ReadableArray1[\T,b0,s0\], |
|---|
| 1914 | StandardMutableArrayType[\Array1[\T,b0,s0\],T,ZZ32\] } |
|---|
| 1915 | excludes {Number, String} |
|---|
| 1916 | |
|---|
| 1917 | getter mutability():String = "" |
|---|
| 1918 | |
|---|
| 1919 | shift(o:ZZ32): Array[\T,ZZ32\] = |
|---|
| 1920 | if o=0 then |
|---|
| 1921 | self |
|---|
| 1922 | else |
|---|
| 1923 | __subarray(self,reflect(o),N[\s0\],N[\b0\]) |
|---|
| 1924 | end |
|---|
| 1925 | |
|---|
| 1926 | opr[r: Range[\ZZ32\]] : Array[\T,ZZ32\] = do |
|---|
| 1927 | r' = (bounds())[r] |
|---|
| 1928 | z = N[\0\] |
|---|
| 1929 | s = reflect( |r'| ) |
|---|
| 1930 | l = reflect(r'.lower()) |
|---|
| 1931 | __subarray(self,z,s,l) |
|---|
| 1932 | end |
|---|
| 1933 | opr[_:OpenRange[\ZZ32\]] : Array1[\T,0,s0\] = |
|---|
| 1934 | subarray[\0,s0,0\]() |
|---|
| 1935 | opr[_:OpenRange[\Any\]] : Array1[\T,0,s0\] = |
|---|
| 1936 | subarray[\0,s0,0\]() |
|---|
| 1937 | |
|---|
| 1938 | (** subarray selects a subarray of this array based on static parameters. |
|---|
| 1939 | b#s are the new bounds of the array; o is |
|---|
| 1940 | the index of the subarray within the current array. **) |
|---|
| 1941 | subarray[\nat b, nat s, nat o\]():Array1[\T, b, s\] = do |
|---|
| 1942 | boundsCheck = (bounds())[o#s] |
|---|
| 1943 | __SimpleSubArray1[\T,b,s,b0,s0\](self,o-b0,1) |
|---|
| 1944 | end |
|---|
| 1945 | |
|---|
| 1946 | (* the replica method returns a replica of the array (similar layout |
|---|
| 1947 | etc.) but with a different element type. *) |
|---|
| 1948 | replica[\U\]():Array1[\U,b0,s0\] = __builtinFactory1[\U,b0,s0\]() |
|---|
| 1949 | |
|---|
| 1950 | copy():Array1[\T,b0,s0\] = |
|---|
| 1951 | replica[\T\]().fill(fn (i:ZZ32):T => get(i-b0)) |
|---|
| 1952 | |
|---|
| 1953 | freeze():ImmutableArray1[\T,b0,s0\] = |
|---|
| 1954 | __immutableFactory1[\T,b0,s0\]().fill(fn (i:ZZ32):T => get(i-b0)) |
|---|
| 1955 | |
|---|
| 1956 | map[\R\](f:T->R): Array1[\R,b0,s0\] = |
|---|
| 1957 | replica[\R\]().fill(fn (i:ZZ32):R => f(get(i-b0))) |
|---|
| 1958 | ivmap[\R\](f:(ZZ32,T)->R): Array1[\R,b0,s0\] = |
|---|
| 1959 | replica[\R\]().fill(fn (i:ZZ32):R => f(i,get(i-b0))) |
|---|
| 1960 | end |
|---|
| 1961 | |
|---|
| 1962 | (* WORK AROUND absence of type inference in method calls. *) |
|---|
| 1963 | __subarray[\T, nat b0, nat s0, nat b, nat s, nat o\] |
|---|
| 1964 | (it:Array1[\T,b0,s0\], |
|---|
| 1965 | _:N[\b\],_:N[\s\],_:N[\o\]):Array1[\T,b,s\] = |
|---|
| 1966 | it.subarray[\b,s,o\]() |
|---|
| 1967 | |
|---|
| 1968 | __subarrayI[\T, nat b0, nat s0, nat b, nat s, nat o\] |
|---|
| 1969 | (it:ImmutableArray1[\T,b0,s0\], |
|---|
| 1970 | _:N[\b\],_:N[\s\],_:N[\o\]):ImmutableArray1[\T,b,s\] = |
|---|
| 1971 | it.subarray[\b,s,o\]() |
|---|
| 1972 | |
|---|
| 1973 | |
|---|
| 1974 | (** A 1-D subarray of an Array1. |
|---|
| 1975 | b_a#s_a is the underlying array's bounds; b0#s0 is the |
|---|
| 1976 | result bounds. o0 is the starting offset in the underlying array, |
|---|
| 1977 | defined in 0-indexed space. m0 the stride within that array. |
|---|
| 1978 | Invariant: (s0-1) m0 + o0 - b_a) < s_a *) |
|---|
| 1979 | object __SimpleSubArray1[\T, nat b0, nat s0, nat b_a, nat s_a\] |
|---|
| 1980 | (arr:Array1[\T,b_a,s_a\], o0:ZZ32, m0:ZZ32) |
|---|
| 1981 | extends Array1[\T, b0, s0\] |
|---|
| 1982 | index(i:ZZ32):T = i m0 + o0 |
|---|
| 1983 | get(i:ZZ32):T = arr.get(index(i)) |
|---|
| 1984 | put(i:ZZ32,v:T): () = arr.put(index(i),v) |
|---|
| 1985 | init0(i:ZZ32,v:T): () = arr.init0(index(i),v) |
|---|
| 1986 | subarray[\nat b, nat s, nat o\]():Array1[\T, b, s\] = do |
|---|
| 1987 | boundsCheck = (bounds())[o#s] |
|---|
| 1988 | o_n : ZZ32 = o - b0 |
|---|
| 1989 | __SimpleSubArray1[\T, b, s, b_a, s_a\](arr, index(o_n), m0) |
|---|
| 1990 | end |
|---|
| 1991 | end |
|---|
| 1992 | |
|---|
| 1993 | (** The same as above, but immutable. **) |
|---|
| 1994 | object __ImmutableSubArray1[\T, nat b0, nat s0, nat b_a, nat s_a\] |
|---|
| 1995 | (arr:ImmutableArray1[\T,b_a,s_a\], o0:ZZ32, m0:ZZ32) |
|---|
| 1996 | extends ImmutableArray1[\T, b0, s0\] |
|---|
| 1997 | index(i:ZZ32):T = i m0 + o0 |
|---|
| 1998 | get(i:ZZ32):T = arr.get(index(i)) |
|---|
| 1999 | put(i:ZZ32,v:T): () = arr.put(index(i),v) |
|---|
| 2000 | init0(i:ZZ32,v:T): () = arr.init0(index(i),v) |
|---|
| 2001 | subarray[\nat b, nat s, nat o\]():ImmutableArray1[\T, b, s\] = do |
|---|
| 2002 | boundsCheck = (bounds())[o#s] |
|---|
| 2003 | o_n : ZZ32 = o - b0 |
|---|
| 2004 | __ImmutableSubArray1[\T, b, s, b_a, s_a\](arr, index(o_n), m0) |
|---|
| 2005 | end |
|---|
| 2006 | end |
|---|
| 2007 | |
|---|
| 2008 | trait AnyVector end |
|---|
| 2009 | |
|---|
| 2010 | trait Vector[\T extends Number, nat s0\] |
|---|
| 2011 | extends { AnyVector, Array1[\T,0,s0\], AdditiveGroup[\Vector[\T,s0\]\] } |
|---|
| 2012 | excludes { AnyMultiplicativeRing } |
|---|
| 2013 | opr +(self, v:Vector[\T,s0\]): Vector[\T,s0\] = |
|---|
| 2014 | ivmap[\T\](fn (i:ZZ32, e: T):T => e + v.get(i)) |
|---|
| 2015 | opr -(self, v:Vector[\T,s0\]): Vector[\T,s0\] = |
|---|
| 2016 | ivmap[\T\](fn (i:ZZ32, e: T):T => e - v.get(i)) |
|---|
| 2017 | opr -(self): Vector[\T,s0\] = map[\T\](fn (e: T):T => - e) |
|---|
| 2018 | scale(t: T): Vector[\T,s0\] = map[\T\](fn (v) => t v) |
|---|
| 2019 | pmul(v: Vector[\T,s0\]): Vector[\T,s0\] = |
|---|
| 2020 | ivmap[\T\](fn (i:ZZ32, e: T):T => e v.get(i)) |
|---|
| 2021 | dot(v: Vector[\T,s0\]): T = |
|---|
| 2022 | SUM [(i,me_i)<-indexValuePairs()] me_i v.get(i) |
|---|
| 2023 | end |
|---|
| 2024 | |
|---|
| 2025 | object __DefaultVector[\T, nat s0\]() extends Vector[\T,s0\] |
|---|
| 2026 | mem: PrimitiveArray[\T,s0\] = PrimitiveArray[\T,s0\]() |
|---|
| 2027 | get(i:ZZ32):T = mem.get(i) |
|---|
| 2028 | put(i:ZZ32, v:T) = mem.put(i,v) |
|---|
| 2029 | init0(i:ZZ32, v:T) = mem.init0(i,v) |
|---|
| 2030 | replica[\U\]() = array1[\U,s0\]() |
|---|
| 2031 | end |
|---|
| 2032 | |
|---|
| 2033 | (* builtinFactory1 must be a non-overloaded 0-parameter factory for |
|---|
| 2034 | 1-D arrays. The type parameters are enshrined in LHSEvaluator.java |
|---|
| 2035 | and NonPrimitive.java; the factory name is enshrined in |
|---|
| 2036 | WellKnownNames.java. There must be some factory, named in this |
|---|
| 2037 | file, with this type signature. A similar thing is true for |
|---|
| 2038 | K-dimensional array types. *) |
|---|
| 2039 | __builtinFactory1[\T, nat b0, nat s0\]():Array1[\T,b0,s0\] = do |
|---|
| 2040 | r = array1[\T,s0\]() |
|---|
| 2041 | typecase _ = N[\b0\] of |
|---|
| 2042 | N[\0\] => r |
|---|
| 2043 | else => r.subarray[\b0,s0,0\]() |
|---|
| 2044 | end |
|---|
| 2045 | end |
|---|
| 2046 | |
|---|
| 2047 | (* immutableFactory1 is a non-overloaded 0-parameter factory for |
|---|
| 2048 | 0-indexed 1-D arrays. It is also mentioned in WellKnownNames as it |
|---|
| 2049 | is used to allocate storage for varargs. *) |
|---|
| 2050 | __immutableFactory1[\T, nat b0, nat s0\]():ReadableArray1[\T,b0,s0\] = do |
|---|
| 2051 | r = immutableArray1[\T,s0\]() |
|---|
| 2052 | typecase _ = N[\b0\] of |
|---|
| 2053 | N[\0\] => r |
|---|
| 2054 | else => r.subarray[\b0,s0,0\]() |
|---|
| 2055 | end |
|---|
| 2056 | end |
|---|
| 2057 | |
|---|
| 2058 | (* TODO: fix when Number is covariant. *) |
|---|
| 2059 | array1[\T, nat s0\]():Array1[\T,0,s0\] = |
|---|
| 2060 | typecase _ = __Proxy[\T\] of |
|---|
| 2061 | __Proxy[\ZZ32\] => vector[\T,s0\]() |
|---|
| 2062 | __Proxy[\ZZ64\] => vector[\T,s0\]() |
|---|
| 2063 | __Proxy[\RR64\] => vector[\T,s0\]() |
|---|
| 2064 | __Proxy[\Number\] => vector[\T,s0\]() |
|---|
| 2065 | else => PrimitiveArray[\T,s0\]() |
|---|
| 2066 | end |
|---|
| 2067 | array1[\T, nat s0\](v:T):Array1[\T,0,s0\] = array1[\T,s0\]().fill(v) |
|---|
| 2068 | array1[\T, nat s0\](f:ZZ32->T):Array1[\T,0,s0\] = array1[\T,s0\]().fill(f) |
|---|
| 2069 | |
|---|
| 2070 | immutableArray1[\T, nat s0\](): ImmutableArray1[\T,0,s0\] = |
|---|
| 2071 | PrimImmutableArray[\T,s0\]() |
|---|
| 2072 | |
|---|
| 2073 | (* vector is the same as array1, but specialized to numeric type arguments *) |
|---|
| 2074 | vector[\T extends Number, nat s0\]():Vector[\T,s0\] = __DefaultVector[\T,s0\]() |
|---|
| 2075 | vector[\T extends Number, nat s0\](v:T):Vector[\T,s0\] = |
|---|
| 2076 | vector[\T,s0\]().fill(v) |
|---|
| 2077 | vector[\T extends Number, nat s0\](f:ZZ32->T):Vector[\T,s0\] = |
|---|
| 2078 | vector[\T,s0\]().fill(f) |
|---|
| 2079 | |
|---|
| 2080 | pmul[\ T extends Number, nat k \] |
|---|
| 2081 | (a : Vector[\T,k\], b : Vector[\T,k\]):Vector[\T,k\] = a.pmul(b) |
|---|
| 2082 | |
|---|
| 2083 | opr DOT[\ T extends Number, nat n \] |
|---|
| 2084 | (me : Vector[\T,n\], other : Vector[\T,n\]):T = me.dot(other) |
|---|
| 2085 | |
|---|
| 2086 | opr juxtaposition[\ T extends Number, nat n \] |
|---|
| 2087 | (me : Vector[\T,n\], other : Vector[\T,n\]):T = me.dot(other) |
|---|
| 2088 | |
|---|
| 2089 | opr DOT[\ T extends Number, nat n \] |
|---|
| 2090 | (me : Vector[\T,n\], other : T) : Vector[\T,n\] = me.scale(other) |
|---|
| 2091 | |
|---|
| 2092 | opr juxtaposition[\ T extends Number, nat n \] |
|---|
| 2093 | (me : Vector[\T,n\], other : T) : Vector[\T,n\] = me.scale(other) |
|---|
| 2094 | |
|---|
| 2095 | opr DOT[\ T extends Number, nat n \] |
|---|
| 2096 | (other : T, me : Vector[\T,n\]) : Vector[\T,n\] = me.scale(other) |
|---|
| 2097 | |
|---|
| 2098 | opr juxtaposition[\ T extends Number, nat n \] |
|---|
| 2099 | (other : T, me : Vector[\T,n\]) : Vector[\T,n\] = me.scale(other) |
|---|
| 2100 | |
|---|
| 2101 | squaredNorm[\T extends Number, nat s0\](a:Vector[\T,s0\]):T = a.dot(a) |
|---|
| 2102 | |
|---|
| 2103 | opr ||[\ T extends Number, nat k \]me : Vector[\T,k\]|| : RR64 = SQRT squaredNorm(me) |
|---|
| 2104 | |
|---|
| 2105 | (** Array2[\T,b0,s0,b1,s1\] is the type of 2-dimensional arrays of |
|---|
| 2106 | element type T, with size s0 in the first dimension and s1 in the |
|---|
| 2107 | second dimension and lowest index (b0,b1). Natural order for all |
|---|
| 2108 | generators in each dimension is from b to b+s-1; the overall order |
|---|
| 2109 | of elements need only be consistent with the cross product of |
|---|
| 2110 | these orderings (see Generator.cross()). **) |
|---|
| 2111 | trait Array2[\T, nat b0, nat s0, nat b1, nat s1\] |
|---|
| 2112 | extends { Indexed1[\s0\], Indexed2[\s1\], Rank2, |
|---|
| 2113 | StandardMutableArrayType[\Array2[\T,b0,s0,b1,s1\],T,(ZZ32,ZZ32)\] } |
|---|
| 2114 | excludes { Number, String } |
|---|
| 2115 | getter size():ZZ32 = s0 s1 |
|---|
| 2116 | getter bounds():Tuple2Range[\ZZ32,ZZ32,true\] = Tuple2Range[\ZZ32,ZZ32,true\](b0,b1,s0,s1) |
|---|
| 2117 | getter toString() = do |
|---|
| 2118 | r : String := "[" b0 "#" s0 "," b1 "#" s1 "] =" |
|---|
| 2119 | row(i) = |
|---|
| 2120 | for j <- seq(0#s1) do |
|---|
| 2121 | r := r " " get(i,j) |
|---|
| 2122 | end |
|---|
| 2123 | if s0 = 0 then |
|---|
| 2124 | r " []" |
|---|
| 2125 | else |
|---|
| 2126 | r := r "\n[" |
|---|
| 2127 | row(0) |
|---|
| 2128 | for i <- seq(1#(s0-1)) do |
|---|
| 2129 | r := r "\n " |
|---|
| 2130 | row(i) |
|---|
| 2131 | end |
|---|
| 2132 | r " ]" |
|---|
| 2133 | end |
|---|
| 2134 | end |
|---|
| 2135 | opr |self| : ZZ32 = s0 s1 |
|---|
| 2136 | (* Translate from b0,b1-indexing to 0-indexing, checking bounds. *) |
|---|
| 2137 | offset(t_1:(ZZ32,ZZ32)):(ZZ32,ZZ32) = do |
|---|
| 2138 | (a0,a1) = t_1 |
|---|
| 2139 | c0 = a0 - b0 |
|---|
| 2140 | c1 = a1 - b1 |
|---|
| 2141 | if NOT (0 <= c0 < s0) then |
|---|
| 2142 | oops(1,b0,s0,a0) |
|---|
| 2143 | elif NOT (0 <= c1 < s1) then |
|---|
| 2144 | oops(2,b1,s1,a1) |
|---|
| 2145 | else |
|---|
| 2146 | (c0,c1) |
|---|
| 2147 | end |
|---|
| 2148 | end |
|---|
| 2149 | toIndex(t_1:(ZZ32,ZZ32)):(ZZ32,ZZ32) = do (a0,a1)=t_1; (a0+b0,a1+b1) end |
|---|
| 2150 | opr[x:ZZ32,y:ZZ32]:=(v:T):() = do self[ (x,y) ] := v end |
|---|
| 2151 | opr[r:Range[\(ZZ32,ZZ32)\]]: Array[\T,(ZZ32,ZZ32)\] = do |
|---|
| 2152 | r' = (bounds())[r] |
|---|
| 2153 | (z0,z1) = r'.extent() |
|---|
| 2154 | (l0,l1) = r'.lower() |
|---|
| 2155 | __subarray(self, N[\0\],reflect(z0), N[\0\], reflect(z1), |
|---|
| 2156 | reflect(l0),reflect(l1)) |
|---|
| 2157 | end |
|---|
| 2158 | opr[_:OpenRange[\ZZ32\]] : Array2[\T,0,s0,0,s1\] = |
|---|
| 2159 | subarray[\0,s0,0,s1,0,0\]() |
|---|
| 2160 | opr[_:OpenRange[\Any\]] : Array2[\T,0,s0,0,s1\] = |
|---|
| 2161 | subarray[\0,s0,0,s1,0,0\]() |
|---|
| 2162 | shift(t_1:(ZZ32,ZZ32)): Array[\T,(ZZ32,ZZ32)\] = do |
|---|
| 2163 | (o0,o1)=t_1 |
|---|
| 2164 | if o0=0 AND o1=0 then |
|---|
| 2165 | self |
|---|
| 2166 | else |
|---|
| 2167 | __subarray(self,reflect(o0),N[\s0\], reflect(o1),N[\s1\], N[\b0\],N[\b1\]) |
|---|
| 2168 | end |
|---|
| 2169 | end |
|---|
| 2170 | |
|---|
| 2171 | (** 2-D subarray given static subarray parameters. |
|---|
| 2172 | (bo1,bo2)#(so1,so2) are output bounds. |
|---|
| 2173 | The result is the subarray starting at (o0,o1) in the original array. |
|---|
| 2174 | **) |
|---|
| 2175 | subarray[\nat bo0, nat so0, nat bo1, nat so1, nat o0, nat o1\] |
|---|
| 2176 | (): Array2[\T,bo0,so0,bo1,so1\] = do |
|---|
| 2177 | boundsCheck = (bounds())[ (o0,o1)#(so0,so1) ] |
|---|
| 2178 | SubArray2[\T,bo0,so0,bo1,so1,b0,s0,b1,s1\](self,1,o0,1,o1) |
|---|
| 2179 | end |
|---|
| 2180 | |
|---|
| 2181 | zeroIndices():Tuple2Range[\ZZ32,ZZ32,true\] = Tuple2Range[\ZZ32,ZZ32,true\](0,0,s0,s1) |
|---|
| 2182 | |
|---|
| 2183 | replica[\U\]():Array2[\U,b0,s0,b1,s1\] = |
|---|
| 2184 | __builtinFactory2[\U,b0,s0,b1,s1\]() |
|---|
| 2185 | copy():Array2[\T,b0,s0,b1,s1\] = |
|---|
| 2186 | self.replica[\T\]().fill(fn (i:ZZ32,j:ZZ32):T => get(i-b0,j-b1)) |
|---|
| 2187 | put(t1:(ZZ32, ZZ32), v:T) : () |
|---|
| 2188 | get(t1:(ZZ32, ZZ32)):T |
|---|
| 2189 | t():Array2[\T,b1,s1,b0,s0\] = TransposedArray2[\T,b1,s1,b0,s0\](self) |
|---|
| 2190 | (* Copied here for better return type information. *) |
|---|
| 2191 | map[\R\](f:T->R): Array2[\R,b0,s0,b1,s1\] = |
|---|
| 2192 | replica[\R\]().fill(fn (i:ZZ32,j:ZZ32):R => f(get(i-b0,j-b1))) |
|---|
| 2193 | ivmap[\R\](f:((ZZ32,ZZ32),T)->R): Array2[\R,b0,s0,b1,s1\] = |
|---|
| 2194 | replica[\R\]().fill(fn (i:ZZ32,j:ZZ32):R => f((i,j),get(i-b0,j-b1))) |
|---|
| 2195 | |
|---|
| 2196 | freeze():ImmutableArray[\T,(ZZ32,ZZ32)\] = fail("Freeze not defined yet!") |
|---|
| 2197 | end |
|---|
| 2198 | |
|---|
| 2199 | (** Hoisted out here to work around the lack of method type inference. **) |
|---|
| 2200 | __subarray[\T, nat b0, nat s0, nat b1, nat s1, |
|---|
| 2201 | nat bo0, nat so0, nat bo1, nat so1, nat o0, nat o1\] |
|---|
| 2202 | (this:Array2[\T,b0,s0,b1,s1\], |
|---|
| 2203 | _:N[\bo0\],_:N[\so0\],_:N[\bo1\],_:N[\so1\], |
|---|
| 2204 | _:N[\o0\],_:N[\o1\]): Array2[\T,bo0,so0,bo1,so1\] = do |
|---|
| 2205 | (* |
|---|
| 2206 | println("__subarray[\\" b0 "," s0 "," b1 "," s1 ", " |
|---|
| 2207 | bo0 "," so0 "," bo1 "," so1 ", " o0 "," o1 "\\]()") |
|---|
| 2208 | *) |
|---|
| 2209 | this.subarray[\bo0,so0,bo1,so1,o0,o1\]() |
|---|
| 2210 | end |
|---|
| 2211 | |
|---|
| 2212 | (** Default array is column-major, but we could switch it. **) |
|---|
| 2213 | object __DefaultArray2[\T, nat b0, nat s0, nat b1, nat s1\]() |
|---|
| 2214 | extends Array2[\T, b0, s0, b1, s1\] |
|---|
| 2215 | mem:PrimitiveArray[\T, (s0 s1) \] = PrimitiveArray[\T, (s0 s1) \]() |
|---|
| 2216 | init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0(i s1 + j, v) end |
|---|
| 2217 | put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put(i s1 + j, v) end |
|---|
| 2218 | get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(i s1 + j) end |
|---|
| 2219 | end |
|---|
| 2220 | |
|---|
| 2221 | (** Transposes the index of the underlying array mem, and transposes |
|---|
| 2222 | its natural order as well. **) |
|---|
| 2223 | object TransposedArray2[\T, nat b0, nat s0, nat b1, nat s1\] |
|---|
| 2224 | (mem:Array2[\T,b1,s1,b0,s0\]) |
|---|
| 2225 | extends Array2[\T, b0, s0, b1, s1\] |
|---|
| 2226 | replica[\U\]():Array2[\U,b0,s0,b1,s1\] = mem.replica[\U\]().t() |
|---|
| 2227 | |
|---|
| 2228 | init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0((j,i),v) end |
|---|
| 2229 | put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put((j,i),v) end |
|---|
| 2230 | get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(j,i) end |
|---|
| 2231 | t() = mem |
|---|
| 2232 | end |
|---|
| 2233 | |
|---|
| 2234 | (** Simple 2-D subarray, used when we have no other knowledge of the |
|---|
| 2235 | underlying structure. If we're on top of a PrimitiveArray we can |
|---|
| 2236 | really do much better than this. |
|---|
| 2237 | (b0,b1)#(s0,s1) are the bounds of the subarray. |
|---|
| 2238 | (bu0,bu1)#(su0,su1) are the bounds of the underlying array. |
|---|
| 2239 | m_i, o_i are multiplier and offset (0-based) of dimension i. |
|---|
| 2240 | **) |
|---|
| 2241 | object SubArray2[\T, nat b0, nat s0, nat b1, nat s1, |
|---|
| 2242 | nat bu0, nat su0, nat bu1, nat su1\] |
|---|
| 2243 | (mem: Array2[\T,bu0,su0,bu1,su1\], |
|---|
| 2244 | m0:ZZ32, o0:ZZ32, m1:ZZ32, o1:ZZ32) |
|---|
| 2245 | extends Array2[\T,b0,s0,b1,s1\] |
|---|
| 2246 | index(a0:ZZ32, a1:ZZ32): (ZZ32,ZZ32) = (m0 a0 + o0, m1 a1 + o1) |
|---|
| 2247 | init0(t_1:(ZZ32,ZZ32), v:T): () = mem.init0(index(t_1),v) |
|---|
| 2248 | put(t_1:(ZZ32,ZZ32), v:T): () = mem.put(index(t_1),v) |
|---|
| 2249 | get(t_1:(ZZ32,ZZ32)): T = mem.get(index(t_1)) |
|---|
| 2250 | end |
|---|
| 2251 | |
|---|
| 2252 | trait AnyMatrix end |
|---|
| 2253 | |
|---|
| 2254 | trait Matrix[\T extends Number, nat s0, nat s1\] |
|---|
| 2255 | extends { AnyMatrix, Array2[\T, 0, s0, 0, s1\], AdditiveGroup[\Matrix[\T,s0,s1\]\] } |
|---|
| 2256 | excludes { AnyMultiplicativeRing } |
|---|
| 2257 | opr +(self, v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = |
|---|
| 2258 | ivmap[\T\](fn (i:(ZZ32,ZZ32),e:T):T => e + v.get(i)) |
|---|
| 2259 | opr -(self, v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = |
|---|
| 2260 | ivmap[\T\](fn (i:(ZZ32,ZZ32),e:T):T => e - v.get(i)) |
|---|
| 2261 | opr -(self): Matrix[\T,s0,s1\] = map[\T\](fn (e:T):T => - e) |
|---|
| 2262 | scale(t_1: T): Matrix[\T,s0,s1\] = map[\T\](fn (e:T):T => t_1 e) |
|---|
| 2263 | mul[\ nat s2 \](other: Matrix[\T,s1,s2\]): Matrix[\T,s0,s2\] = do |
|---|
| 2264 | res = matrix[\T,s0,s2\]() |
|---|
| 2265 | mma(a:ZZ32,i:ZZ32,b:ZZ32,j:ZZ32,c:ZZ32,k:ZZ32):() = |
|---|
| 2266 | if k>=i AND k>=j then |
|---|
| 2267 | if k=1 then |
|---|
| 2268 | pr : T = get(a,b) other.get(b,c) |
|---|
| 2269 | (* If this were atomic, we could parallelize j-partition. *) |
|---|
| 2270 | res.put((a,c), res.get(a,c) + pr) |
|---|
| 2271 | else |
|---|
| 2272 | (k0,k1) = partition(k) |
|---|
| 2273 | (mma(a,i,b,j,c,k0),mma(a,i,b,j,c+k0,k1)) |
|---|
| 2274 | end |
|---|
| 2275 | elif j>=i then |
|---|
| 2276 | (j0,j1) = partition(j) |
|---|
| 2277 | mma(a,i,b,j0,c,k) |
|---|
| 2278 | mma(a,i,b+j0,j1,c,k) |
|---|
| 2279 | else |
|---|
| 2280 | (i0,i1) = partition(i) |
|---|
| 2281 | (mma(a,i0,b,j,c,k),mma(a+i0,i1,b,j,c,k)) |
|---|
| 2282 | end |
|---|
| 2283 | mm(a:ZZ32,i:ZZ32,b:ZZ32,j:ZZ32,c:ZZ32,k:ZZ32):() = |
|---|
| 2284 | if k>=i AND k>=j then |
|---|
| 2285 | if k=1 then |
|---|
| 2286 | res.put((a,c), get(a,b) other.get(b,c)) |
|---|
| 2287 | else |
|---|
| 2288 | (k0,k1) = partition(k) |
|---|
| 2289 | (mm(a,i,b,j,c,k0),mm(a,i,b,j,c+k0,k1)) |
|---|
| 2290 | end |
|---|
| 2291 | elif j>=i then |
|---|
| 2292 | (j0,j1) = partition(j) |
|---|
| 2293 | mm(a,i,b,j0,c,k) |
|---|
| 2294 | mma(a,i,b+j0,j1,c,k) |
|---|
| 2295 | else |
|---|
| 2296 | (i0,i1) = partition(i) |
|---|
| 2297 | (mm(a,i0,b,j,c,k),mm(a+i0,i1,b,j,c,k)) |
|---|
| 2298 | end |
|---|
| 2299 | if s0=0 OR s1=0 OR s2=0 then |
|---|
| 2300 | res |
|---|
| 2301 | else |
|---|
| 2302 | mm(0,s0,0,s1,0,s2) |
|---|
| 2303 | res |
|---|
| 2304 | end |
|---|
| 2305 | end |
|---|
| 2306 | rmul(v: Vector[\T,s1\]): Vector[\T,s0\] = do |
|---|
| 2307 | row(i:ZZ32):T = |
|---|
| 2308 | SUM[(j,v_j)<-v.indexValuePairs] get(i,j) v_j |
|---|
| 2309 | vector[\T,s0\]().fill(row) |
|---|
| 2310 | end |
|---|
| 2311 | lmul(v: Vector[\T,s0\]): Vector[\T,s1\] = do |
|---|
| 2312 | col(i:ZZ32):T = |
|---|
| 2313 | SUM[(j,v_j)<-v.indexValuePairs] v_j get(j,i) |
|---|
| 2314 | vector[\T,s1\]().fill(col) |
|---|
| 2315 | end |
|---|
| 2316 | t(): Matrix[\T,s1,s0\] = TransposedMatrix[\T,s1,s0\](self) |
|---|
| 2317 | end |
|---|
| 2318 | |
|---|
| 2319 | (* Default matrix should match default array in column vs row-major. *) |
|---|
| 2320 | object __DefaultMatrix[\T, nat s0, nat s1\]() |
|---|
| 2321 | extends Matrix[\T, s0, s1\] |
|---|
| 2322 | mem:PrimitiveArray[\T, (s0 s1) \] = PrimitiveArray[\T, (s0 s1) \]() |
|---|
| 2323 | init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0(i s1 + j, v) end |
|---|
| 2324 | put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put(i s1 + j, v) end |
|---|
| 2325 | get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(i s1 + j) end |
|---|
| 2326 | end |
|---|
| 2327 | |
|---|
| 2328 | object TransposedMatrix[\T, nat s0, nat s1\](mem:Matrix[\T,s1,s0\]) |
|---|
| 2329 | extends Matrix[\T, s0, s1\] |
|---|
| 2330 | replica[\U\]():Array2[\U,0,s0,0,s1\] = mem.replica[\U\]().t() |
|---|
| 2331 | |
|---|
| 2332 | init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0((j,i),v) end |
|---|
| 2333 | put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put((j,i),v) end |
|---|
| 2334 | get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(j,i) end |
|---|
| 2335 | t(): Matrix[\T,s1,s0\] = mem |
|---|
| 2336 | add(v:TransposedMatrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = mem.add(v.t()).t() |
|---|
| 2337 | subtract(v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = mem.subtract(v.t()).t() |
|---|
| 2338 | negate(): Matrix[\T,s0,s1\] = mem.negate().t() |
|---|
| 2339 | scale(f: T): Matrix[\T,s0,s1\] = mem.scale(f).t() |
|---|
| 2340 | rmul(v: Vector[\T,s1\]): Vector[\T,s0\] = mem.lmul(v) |
|---|
| 2341 | lmul(v: Vector[\T,s0\]): Vector[\T,s1\] = mem.rmul(v) |
|---|
| 2342 | (* Can't overload generic methods yet, but this is preferable. |
|---|
| 2343 | mul[\nat s2\](v:TransposedMatrix[\T,s1,s2\]): Matrix[\T,s0,s2\] = |
|---|
| 2344 | v.t().mul(mem).t() |
|---|
| 2345 | *) |
|---|
| 2346 | end |
|---|
| 2347 | |
|---|
| 2348 | __builtinFactory2[\T,nat b0,nat s0,nat b1,nat s1\]():Array2[\T,b0,s0,b1,s1\] = |
|---|
| 2349 | if b0=0 AND b1=0 then |
|---|
| 2350 | array2[\T,s0,s1\]() |
|---|
| 2351 | else |
|---|
| 2352 | __DefaultArray2[\T,b0,s0,b1,s1\]() |
|---|
| 2353 | end |
|---|
| 2354 | |
|---|
| 2355 | (* array2 is a factory for 0-based 2-D arrays. *) |
|---|
| 2356 | (* TODO: fix when Number is covariant. *) |
|---|
| 2357 | array2[\T, nat s0, nat s1\]():Array2[\T,0,s0,0,s1\] = |
|---|
| 2358 | typecase _ = __Proxy[\T\] of |
|---|
| 2359 | __Proxy[\ZZ32\] => matrix[\T,s0,s1\]() |
|---|
| 2360 | __Proxy[\ZZ64\] => matrix[\T,s0,s1\]() |
|---|
| 2361 | __Proxy[\RR64\] => matrix[\T,s0,s1\]() |
|---|
| 2362 | __Proxy[\Number\] => matrix[\T,s0,s1\]() |
|---|
| 2363 | else => __DefaultArray2[\T,0,s0,0,s1\]() |
|---|
| 2364 | end |
|---|
| 2365 | array2[\T, nat s0, nat s1\](v:T):Array2[\T,0,s0,0,s1\] = |
|---|
| 2366 | array2[\T,s0,s1\]().fill(v) |
|---|
| 2367 | array2[\T, nat s0, nat s1\](f:(ZZ32,ZZ32)->T):Array2[\T,0,s0,0,s1\] = |
|---|
| 2368 | array2[\T,s0,s1\]().fill(f) |
|---|
| 2369 | |
|---|
| 2370 | (* matrix is the same as array1, but specialized to numeric type |
|---|
| 2371 | arguments, except that the default value (if given) is used to |
|---|
| 2372 | construct a multiple of the identity matrix. *) |
|---|
| 2373 | matrix[\T extends Number, nat s0, nat s1\]():Matrix[\T,s0,s1\] = |
|---|
| 2374 | __DefaultMatrix[\T,s0,s1\]() |
|---|
| 2375 | matrix[\T extends Number, nat s0, nat s1\](v:T):Matrix[\T,s0,s1\] = |
|---|
| 2376 | array2[\T,s0,s1\]().fill(fn (x:ZZ32,y:ZZ32):T => if x=y then v else 0 end) |
|---|
| 2377 | |
|---|
| 2378 | (* Matrix multiplication; used to use a cache-oblivious algorithm, but |
|---|
| 2379 | we ran into trouble due to lack of support for atomic increment of |
|---|
| 2380 | matrix elements. *) |
|---|
| 2381 | opr DOT[\ T extends Number, nat n, nat m, nat p\] |
|---|
| 2382 | (me:Matrix[\T,n,m\], other:Matrix[\T,m,p\]): Matrix[\T,n,p\] = |
|---|
| 2383 | me.mul[\p\](other) |
|---|
| 2384 | |
|---|
| 2385 | opr juxtaposition[\ T extends Number, nat n, nat m, nat p\] |
|---|
| 2386 | (me:Matrix[\T,n,m\], other:Matrix[\T,m,p\]): Matrix[\T,n,p\] = |
|---|
| 2387 | me.mul[\p\](other) |
|---|
| 2388 | |
|---|
| 2389 | |
|---|
| 2390 | (* matrix-vector multiplication *) |
|---|
| 2391 | opr DOT[\ T extends Number, nat n, nat m \] |
|---|
| 2392 | (me:Matrix[\T,n,m\], v:Vector[\T,m\]):Vector[\T,n\] = me.rmul(v) |
|---|
| 2393 | |
|---|
| 2394 | opr juxtaposition[\ T extends Number, nat n, nat m \] |
|---|
| 2395 | (me:Matrix[\T,n,m\], v:Vector[\T,m\]):Vector[\T,n\] = me.rmul(v) |
|---|
| 2396 | |
|---|
| 2397 | (* vector-matrix multiplication *) |
|---|
| 2398 | opr DOT[\ T extends Number, nat n, nat m \] |
|---|
| 2399 | (v:Vector[\T,n\], me:Matrix[\T,n,m\]):Vector[\T,m\] = me.lmul(v) |
|---|
| 2400 | |
|---|
| 2401 | opr juxtaposition[\ T extends Number, nat n, nat m \] |
|---|
| 2402 | (v:Vector[\T,n\], me:Matrix[\T,n,m\]):Vector[\T,m\] = me.lmul(v) |
|---|
| 2403 | |
|---|
| 2404 | opr DOT[\ T extends Number, nat n, nat m \] |
|---|
| 2405 | (me : Matrix[\T,n,m\], other : T) : Matrix[\T,n,m\] = me.scale(other) |
|---|
| 2406 | |
|---|
| 2407 | opr juxtaposition[\ T extends Number, nat n, nat m \] |
|---|
| 2408 | (me : Matrix[\T,n,m\], other : T) : Matrix[\T,n,m\] = me.scale(other) |
|---|
| 2409 | |
|---|
| 2410 | opr DOT[\ T extends Number, nat n, nat m \] |
|---|
| 2411 | (other : T, me : Matrix[\T,n,m\]) : Matrix[\T,n,m\] = me.scale(other) |
|---|
| 2412 | |
|---|
| 2413 | opr juxtaposition[\ T extends Number, nat n, nat m \] |
|---|
| 2414 | (other : T, me : Matrix[\T,n,m\]) : Matrix[\T,n,m\] = me.scale(other) |
|---|
| 2415 | |
|---|
| 2416 | (** Array3[\T,b0,s0,b1,s1,b2,s2\] is the type of 3-dimensional arrays |
|---|
| 2417 | of element type T, with size s_i in the i^th dimension and lowest |
|---|
| 2418 | index (b0,b1,b2). Natural order for all generators in each |
|---|
| 2419 | dimension is from b to b+s-1; the overall order of elements need |
|---|
| 2420 | only be consistent with the cross product of these orderings (see |
|---|
| 2421 | Generator.cross()). **) |
|---|
| 2422 | trait Array3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\] |
|---|
| 2423 | extends { Indexed1[\s0\], Indexed2[\s1\], Indexed3[\s2\], Rank3, |
|---|
| 2424 | StandardMutableArrayType[\Array3[\T,b0,s0,b1,s1,b2,s2\],T, |
|---|
| 2425 | (ZZ32,ZZ32,ZZ32)\] } |
|---|
| 2426 | excludes { Number, String } |
|---|
| 2427 | |
|---|
| 2428 | getter size():ZZ32 = s0 s1 s2 |
|---|
| 2429 | getter bounds():Tuple3Range[\ZZ32,ZZ32,ZZ32,true\] = |
|---|
| 2430 | Tuple3Range[\ZZ32,ZZ32,ZZ32,true\](b0,b1,b2,s0,s1,s2) |
|---|
| 2431 | |
|---|
| 2432 | getter toString():String = do |
|---|
| 2433 | r : String := "[" b0 "#" s0 "," b1 "#" s1 "," b2 "#" s2 "] =" |
|---|
| 2434 | row(i,k) = |
|---|
| 2435 | for j <- seq(0#s1) do |
|---|
| 2436 | r := r " " self[b0+i,b1+j,b2+k] |
|---|
| 2437 | end |
|---|
| 2438 | plane(k) = |
|---|
| 2439 | if s1 > 0 then |
|---|
| 2440 | row(0,k) |
|---|
| 2441 | for i <- seq(1#(s0-1)) do |
|---|
| 2442 | r := r "\n " |
|---|
| 2443 | row(i,k) |
|---|
| 2444 | end |
|---|
| 2445 | end |
|---|
| 2446 | if s0=0 then |
|---|
| 2447 | r " []" |
|---|
| 2448 | else |
|---|
| 2449 | r := r "\n[" |
|---|
| 2450 | plane(0) |
|---|
| 2451 | for k <- seq(1#(s2-1)) do |
|---|
| 2452 | r := r " ;;\n " |
|---|
| 2453 | plane(k) |
|---|
| 2454 | end |
|---|
| 2455 | r " ]" |
|---|
| 2456 | end |
|---|
| 2457 | end |
|---|
| 2458 | |
|---|
| 2459 | opr |self| : ZZ32 = s0 s1 s2 |
|---|
| 2460 | |
|---|
| 2461 | (* Again, offset performs bounds checking and shifts to 0 indexing. *) |
|---|
| 2462 | offset(t:(ZZ32,ZZ32,ZZ32)):(ZZ32,ZZ32,ZZ32) = do |
|---|
| 2463 | (a0,a1,a2)=t |
|---|
| 2464 | c0 = a0 - b0; c1 = a1 - b1; c2 = a2 - b2 |
|---|
| 2465 | if NOT (0 <= c0 < s0) then oops(1, b0, s0, a0); end |
|---|
| 2466 | if NOT (0 <= c1 < s1) then oops(2, b1, s1, a1); end |
|---|
| 2467 | if NOT (0 <= c2 < s2) then oops(3, b2, s2, a2); end |
|---|
| 2468 | (c0,c1,c2) |
|---|
| 2469 | end |
|---|
| 2470 | toIndex(t:(ZZ32,ZZ32,ZZ32)):(ZZ32,ZZ32,ZZ32) = |
|---|
| 2471 | do (a0,a1,a2) = t; (a0+b0,a1+b1,a2+b2) end |
|---|
| 2472 | |
|---|
| 2473 | (* And get and put are 0-indexed without bounds checks. *) |
|---|
| 2474 | put(t:(ZZ32,ZZ32,ZZ32), v:T) : () |
|---|
| 2475 | get(t:(ZZ32,ZZ32,ZZ32)):T |
|---|
| 2476 | |
|---|
| 2477 | opr[i:ZZ32, j:ZZ32, k:ZZ32] := (v:T) = do self[ (i,j,k) ] := v end |
|---|
| 2478 | opr[r:Range[\(ZZ32,ZZ32,ZZ32)\]]: Array[\T,(ZZ32,ZZ32,ZZ32)\] = do |
|---|
| 2479 | r' = (bounds())[r] |
|---|
| 2480 | (z0,z1,z2) = r'.extent() |
|---|
| 2481 | (l0,l1,l2) = r'.lower() |
|---|
| 2482 | __subarray(self, N[\0\],reflect(z0), N[\0\],reflect(z1), |
|---|
| 2483 | N[\0\],reflect(z2), reflect(l0),reflect(l1), reflect(l2)) |
|---|
| 2484 | end |
|---|
| 2485 | opr[_:OpenRange[\ZZ32\]] : Array3[\T,0,s0,0,s1,0,s2\] = |
|---|
| 2486 | subarray[\0,s0,0,s1,0,s2,0,0,0\]() |
|---|
| 2487 | opr[_:OpenRange[\Any\]] : Array3[\T,0,s0,0,s1,0,s2\] = |
|---|
| 2488 | subarray[\0,s0,0,s1,0,s2,0,0,0\]() |
|---|
| 2489 | shift(t:(ZZ32,ZZ32,ZZ32)): Array[\T,(ZZ32,ZZ32)\] = do |
|---|
| 2490 | (o0,o1,o2)=t |
|---|
| 2491 | if o0=0 AND o1=0 AND o2=0 then |
|---|
| 2492 | self |
|---|
| 2493 | else |
|---|
| 2494 | __subarray(self, |
|---|
| 2495 | reflect(o0),N[\s0\], reflect(o1),N[\s1\], |
|---|
| 2496 | reflect(o2),N[\s2\], N[\b0\],N[\b1\],N[\b2\]) |
|---|
| 2497 | end |
|---|
| 2498 | end |
|---|
| 2499 | |
|---|
| 2500 | (** 3-D subarray given static subarray parameters. |
|---|
| 2501 | (bo1,bo2)#(so1,so2) are output bounds. |
|---|
| 2502 | The result is the subarray starting at (o0,o1) in the original array. |
|---|
| 2503 | **) |
|---|
| 2504 | subarray[\nat bo0, nat so0, nat bo1, nat so1, nat bo2, nat so2, |
|---|
| 2505 | nat o0, nat o1, nat o2\] |
|---|
| 2506 | (): Array3[\T,bo0,so0,bo1,so1,bo2,so2\] = do |
|---|
| 2507 | boundsCheck = (bounds())[ (o0,o1,o2)#(so0,so1,so2) ] |
|---|
| 2508 | SubArray3[\T,bo0,so0,bo1,so1,bo2,so2,b0,s0,b1,s1,b2,s2\](self,1,o0,1,o1,1,o2) |
|---|
| 2509 | end |
|---|
| 2510 | |
|---|
| 2511 | zeroIndices():Tuple3Range[\ZZ32,ZZ32,ZZ32,true\] = |
|---|
| 2512 | Tuple3Range[\ZZ32,ZZ32,ZZ32,true\](0,0,0,s0,s1,s2) |
|---|
| 2513 | |
|---|
| 2514 | replica[\U\]():Array3[\U,b0,s0,b1,s1,b2,s2\] = |
|---|
| 2515 | __DefaultArray3[\U,b0,s0,b1,s1,b2,s2\]() |
|---|
| 2516 | copy():Array3[\T,b0,s0,b1,s1,b2,s2\] = |
|---|
| 2517 | self.replica[\T\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):T => |
|---|
| 2518 | get(i-b0,j-b1,k-b2)) |
|---|
| 2519 | map[\R\](f:T->R): Array3[\R,b0,s0,b1,s1,b2,s2\] = |
|---|
| 2520 | replica[\R\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):R => |
|---|
| 2521 | f(get(i-b0,j-b1,k-b2))) |
|---|
| 2522 | ivmap[\R\](f:((ZZ32,ZZ32,ZZ32),T)->R): Array3[\R,b0,s0,b1,s1,b2,s2\] = |
|---|
| 2523 | replica[\R\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):R => |
|---|
| 2524 | f((i,j,k),get(i-b0,j-b1,k-b2))) |
|---|
| 2525 | |
|---|
| 2526 | freeze():ImmutableArray[\T,(ZZ32,ZZ32,ZZ32)\] = |
|---|
| 2527 | fail("Freeze not defined yet!") |
|---|
| 2528 | end |
|---|
| 2529 | |
|---|
| 2530 | (** hoisted out here to work around absence of type inference for methods. **) |
|---|
| 2531 | __subarray[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2, |
|---|
| 2532 | nat bo0, nat so0, nat bo1, nat so1, nat bo2, nat so2, |
|---|
| 2533 | nat o0, nat o1, nat o2\] |
|---|
| 2534 | (this:Array3[\T,b0,s0,b1,s1,b2,s2\], |
|---|
| 2535 | _:N[\bo0\],_:N[\so0\],_:N[\bo1\],_:N[\so1\],_:N[\bo2\],_:N[\so2\], |
|---|
| 2536 | _:N[\o0\],_:N[\o1\],_:N[\o2\]): Array3[\T,bo0,so0,bo1,so1,bo2,so2\] = |
|---|
| 2537 | this.subarray[\bo0,so0,bo1,so1,bo2,so2,o0,o1,o2\]() |
|---|
| 2538 | |
|---|
| 2539 | object __DefaultArray3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\]() extends |
|---|
| 2540 | Array3[\T, b0, s0, b1, s1, b2, s2\] |
|---|
| 2541 | mem:PrimitiveArray[\T,(s0 (s1 s2))\] = PrimitiveArray[\T,(s0 (s1 s2))\]() |
|---|
| 2542 | |
|---|
| 2543 | ofs(i:ZZ32,j:ZZ32,k:ZZ32):ZZ32 = (i s1 + j) s2 + k |
|---|
| 2544 | |
|---|
| 2545 | init0(t:(ZZ32,ZZ32,ZZ32), v:T) : () = mem.init0(ofs(t),v) |
|---|
| 2546 | put(t:(ZZ32,ZZ32,ZZ32), v:T) : () = mem.put(ofs(t),v) |
|---|
| 2547 | get(t:(ZZ32,ZZ32,ZZ32)) : T = mem.get(ofs(t)) |
|---|
| 2548 | end |
|---|
| 2549 | |
|---|
| 2550 | (** Simple 3-D subarray, used when we have no other knowledge of the |
|---|
| 2551 | underlying structure. If we're on top of a PrimitiveArray we can |
|---|
| 2552 | really do much better than this. |
|---|
| 2553 | (b0,b1,b2)#(s0,s1,s2) are the bounds of the subarray. |
|---|
| 2554 | (bu0,bu1,bu2)#(su0,su1,su2) are the bounds of the underlying array. |
|---|
| 2555 | m_i, o_i are multiplier and offset (0-based) of dimension i. |
|---|
| 2556 | **) |
|---|
| 2557 | object SubArray3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2, |
|---|
| 2558 | nat bu0, nat su0, nat bu1, nat su1, nat bu2, nat su2\] |
|---|
| 2559 | (mem: Array3[\T,bu0,su0,bu1,su1,bu2,su2\], |
|---|
| 2560 | m0:ZZ32,o0:ZZ32, m1:ZZ32,o1:ZZ32, m2:ZZ32, o2:ZZ32) |
|---|
| 2561 | extends Array3[\T,b0,s0,b1,s1,b2,s2\] |
|---|
| 2562 | index(a0:ZZ32, a1:ZZ32, a2:ZZ32): (ZZ32,ZZ32,ZZ32) = |
|---|
| 2563 | (m0 a0 + o0, m1 a1 + o1, m2 a2 + o2) |
|---|
| 2564 | init0(t:(ZZ32,ZZ32,ZZ32), v:T): () = mem.init0(index(t),v) |
|---|
| 2565 | put(t:(ZZ32,ZZ32,ZZ32), v:T): () = mem.put(index(t),v) |
|---|
| 2566 | get(t:(ZZ32,ZZ32,ZZ32)): T = mem.get(index(t)) |
|---|
| 2567 | end |
|---|
| 2568 | |
|---|
| 2569 | __builtinFactory3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\](): |
|---|
| 2570 | Array3[\T,b0,s0,b1,s1,b2,s2\] = |
|---|
| 2571 | __DefaultArray3[\T,b0,s0,b1,s1,b2,s2\]() |
|---|
| 2572 | |
|---|
| 2573 | array3[\T,nat s0, nat s1, nat s2\]():Array3[\T,0,s0,0,s1,0,s2\] = |
|---|
| 2574 | __DefaultArray3[\T,0,s0,0,s1,0,s2\]() |
|---|
| 2575 | |
|---|
| 2576 | (************* |
|---|
| 2577 | |
|---|
| 2578 | trait Monoid[\ T, opr OPLUS \] |
|---|
| 2579 | where { T extends Monoid[\ T, OPLUS \] } |
|---|
| 2580 | zero() : T |
|---|
| 2581 | opr OPLUS(self, other:T):T |
|---|
| 2582 | end |
|---|
| 2583 | |
|---|
| 2584 | *************) |
|---|
| 2585 | |
|---|
| 2586 | (************************************************************ |
|---|
| 2587 | * Reductions |
|---|
| 2588 | ************************************************************) |
|---|
| 2589 | |
|---|
| 2590 | trait Reduction[\L\] |
|---|
| 2591 | empty(): L |
|---|
| 2592 | join(a: L, b: L): L |
|---|
| 2593 | end |
|---|
| 2594 | |
|---|
| 2595 | (** Invariants: |
|---|
| 2596 | join must be associative with identity empty |
|---|
| 2597 | unlift(lift(x)) = x |
|---|
| 2598 | **) |
|---|
| 2599 | trait ActualReduction[\R,L\] extends Reduction[\L\] |
|---|
| 2600 | getter toString():String |
|---|
| 2601 | lift(r: Any): L |
|---|
| 2602 | unlift(l:L): R |
|---|
| 2603 | (** If this reduction left-distributes over r, return a pair of |
|---|
| 2604 | reductions with the same lift and unlift **) |
|---|
| 2605 | leftDistribute(r: Reduction[\R\]): SomeReductionPair[\R\] = |
|---|
| 2606 | distribute(r) |
|---|
| 2607 | (** If this reduction right-distributes over r, return a pair of |
|---|
| 2608 | reductions with the same lift and unlift **) |
|---|
| 2609 | rightDistribute(r: Reduction[\R\]): SomeReductionPair[\R\] = |
|---|
| 2610 | distribute(r) |
|---|
| 2611 | (** If this reduction distributes over r, return a pair of |
|---|
| 2612 | reductions with the same lift and unlift **) |
|---|
| 2613 | distribute[\K\](r: ActualReduction[\R,K\]): SomeReductionPair[\R\] = |
|---|
| 2614 | NoReductionPair[\R\] |
|---|
| 2615 | end |
|---|
| 2616 | |
|---|
| 2617 | trait PossibleReductionPair[\R\] extends Condition[\SomeReductionPair[\R\]\] |
|---|
| 2618 | comprises { NoReductionPair[\R\], SomeReductionPair[\R\] } |
|---|
| 2619 | end |
|---|
| 2620 | |
|---|
| 2621 | object NoReductionPair[\R\] extends PossibleReductionPair[\R\] |
|---|
| 2622 | getter holds(): Boolean = false |
|---|
| 2623 | getter cond[\G\](t:PossibleReductionPair[\R\]->G, e:()->G): G = e() |
|---|
| 2624 | end |
|---|
| 2625 | |
|---|
| 2626 | trait SomeReductionPair[\R\] extends PossibleReductionPair[\R\] |
|---|
| 2627 | getter holds(): Boolean = true |
|---|
| 2628 | getter cond[\G\](t:PossibleReductionPair[\R\]->G, e:()->G): G = t(self) |
|---|
| 2629 | getter outer(): Reduction[\R\] |
|---|
| 2630 | getter inner(): Reduction[\R\] |
|---|
| 2631 | end |
|---|
| 2632 | |
|---|
| 2633 | trait ReductionPair[\R,L\] extends SomeReductionPair[\R\] |
|---|
| 2634 | getter outer(): ActualReduction[\R,L\] |
|---|
| 2635 | getter inner(): ActualReduction[\R,L\] |
|---|
| 2636 | end |
|---|
| 2637 | |
|---|
| 2638 | (** The usual lifting to Maybe for identity-less operators **) |
|---|
| 2639 | trait AssociativeReduction[\R\] extends ActualReduction[\R,AnyMaybe\] |
|---|
| 2640 | empty(): Nothing[\R\] = Nothing[\R\] |
|---|
| 2641 | join(a: AnyMaybe, b: AnyMaybe): AnyMaybe = |
|---|
| 2642 | if av <- a then |
|---|
| 2643 | if bv <- b then |
|---|
| 2644 | Just(simpleJoin(av,bv)) |
|---|
| 2645 | else |
|---|
| 2646 | a |
|---|
| 2647 | end |
|---|
| 2648 | else |
|---|
| 2649 | b |
|---|
| 2650 | end |
|---|
| 2651 | simpleJoin(a:Any, b:Any): Any |
|---|
| 2652 | lift(r:Any): AnyMaybe = Just(r) |
|---|
| 2653 | unlift(r:AnyMaybe): R = r.get |
|---|
| 2654 | end |
|---|
| 2655 | |
|---|
| 2656 | trait CommutativeReduction[\R\] extends AssociativeReduction[\R\] end |
|---|
| 2657 | |
|---|
| 2658 | (** Monoids don't require a special lift and unlift operation. **) |
|---|
| 2659 | trait MonoidReduction[\R\] extends ActualReduction[\R,R\] |
|---|
| 2660 | lift(r:Any): R = r |
|---|
| 2661 | unlift(r:R): R = r |
|---|
| 2662 | end |
|---|
| 2663 | |
|---|
| 2664 | trait CommutativeMonoidReduction[\R\] extends MonoidReduction[\R\] end |
|---|
| 2665 | |
|---|
| 2666 | trait ReductionWithZeroes[\R,L\] extends ActualReduction[\R,L\] |
|---|
| 2667 | isLeftZero(l:L): Boolean = isZero(l) |
|---|
| 2668 | isRightZero(l:L): Boolean = isZero(l) |
|---|
| 2669 | isZero(l:L): Boolean = false |
|---|
| 2670 | end |
|---|
| 2671 | |
|---|
| 2672 | trait BigOperator[\I,O,R,L\] |
|---|
| 2673 | getter reduction(): ActualReduction[\R,L\] |
|---|
| 2674 | getter body(): I->R |
|---|
| 2675 | getter unwrap(): R->O |
|---|
| 2676 | end |
|---|
| 2677 | |
|---|
| 2678 | object BigReduction[\R,L\](r:ActualReduction[\R,L\]) extends BigOperator[\R,R,R,L\] |
|---|
| 2679 | getter reduction(): ActualReduction[\R,L\] = r |
|---|
| 2680 | getter body(): R->R = fn x => x |
|---|
| 2681 | getter unwrap(): R->R = fn x => x |
|---|
| 2682 | end |
|---|
| 2683 | |
|---|
| 2684 | object Comprehension[\I,O,R,L\](u: R->O, r: ActualReduction[\R,L\], singleton:I->R) |
|---|
| 2685 | extends BigOperator[\I,O,R,L\] |
|---|
| 2686 | getter reduction(): ActualReduction[\R,L\] = r |
|---|
| 2687 | getter body(): I->R = singleton |
|---|
| 2688 | getter unwrap(): R->O = u |
|---|
| 2689 | end |
|---|
| 2690 | |
|---|
| 2691 | (** VoidReduction is usually done for effect, so we pretend that |
|---|
| 2692 | the completion performs the effects. This rules out things |
|---|
| 2693 | distributing over void (that would change the number of effects in |
|---|
| 2694 | our program) but not void distributing over other things. **) |
|---|
| 2695 | object VoidReduction extends { CommutativeMonoidReduction[\()\] } |
|---|
| 2696 | getter toString() = "VoidReduction" |
|---|
| 2697 | empty(): () = () |
|---|
| 2698 | join(a: (), b: ()): () = () |
|---|
| 2699 | end |
|---|
| 2700 | |
|---|
| 2701 | (* Hack to permit any Number to work non-parametrically. *) |
|---|
| 2702 | object SumReduction extends CommutativeMonoidReduction[\Number\] |
|---|
| 2703 | getter toString() = "SumReduction" |
|---|
| 2704 | empty(): Number = 0 |
|---|
| 2705 | join(a: Number, b: Number): Number = a+b |
|---|
| 2706 | end |
|---|
| 2707 | |
|---|
| 2708 | opr SUM[\T extends Number\](): Comprehension[\T,Number,Number,Number\] = |
|---|
| 2709 | Comprehension[\T,Number,Number,Number\](fn x => x, SumReduction, cast[\Number\]) |
|---|
| 2710 | |
|---|
| 2711 | object ProdReduction extends CommutativeMonoidReduction[\Number\] |
|---|
| 2712 | getter toString() = "ProdReduction" |
|---|
| 2713 | empty(): Number = 1 |
|---|
| 2714 | join(a:Number, b:Number): Number = a b |
|---|
| 2715 | end |
|---|
| 2716 | |
|---|
| 2717 | opr PROD[\T extends Number\](): Comprehension[\T,Number,Number,Number\] = |
|---|
| 2718 | Comprehension[\T,Number,Number,Number\](fn x => x, ProdReduction, cast[\Number\]) |
|---|
| 2719 | |
|---|
| 2720 | object MinReduction[\T extends StandardMin[\T\]\] extends CommutativeReduction[\T\] |
|---|
| 2721 | getter toString() = "MinReduction" |
|---|
| 2722 | simpleJoin(a, b) = a MIN b |
|---|
| 2723 | end |
|---|
| 2724 | |
|---|
| 2725 | opr BIG MIN[\T extends StandardMin[\T\]\](): BigReduction[\T,AnyMaybe\] = |
|---|
| 2726 | BigReduction[\T,AnyMaybe\](MinReduction[\T\]) |
|---|
| 2727 | |
|---|
| 2728 | object MaxReduction[\T extends StandardMax[\T\]\] extends CommutativeReduction[\T\] |
|---|
| 2729 | getter toString() = "MaxReduction" |
|---|
| 2730 | simpleJoin(a, b) = a MAX b |
|---|
| 2731 | end |
|---|
| 2732 | |
|---|
| 2733 | opr BIG MAX[\T extends StandardMax[\T\]\](): BigReduction[\T,AnyMaybe\] = |
|---|
| 2734 | BigReduction[\T,AnyMaybe\](MaxReduction[\T\]) |
|---|
| 2735 | |
|---|
| 2736 | opr BIG MINNUM(): BigReduction[\RR64,RR64\] = |
|---|
| 2737 | BigReduction[\RR64,RR64\]( |
|---|
| 2738 | MapReduceReduction[\RR64\](fn (a:RR64,b:RR64):RR64 => a MINNUM b, 0.0/0.0)) |
|---|
| 2739 | |
|---|
| 2740 | opr BIG MAXNUM(): BigReduction[\RR64,RR64\] = |
|---|
| 2741 | BigReduction[\RR64,RR64\]( |
|---|
| 2742 | MapReduceReduction[\RR64\](fn (a:RR64,b:RR64):RR64 => a MAXNUM b, 0.0/0.0)) |
|---|
| 2743 | |
|---|
| 2744 | (** AndReduction and OrReduction take advantage of natural zeroes for early exit. **) |
|---|
| 2745 | object AndReduction |
|---|
| 2746 | extends { CommutativeMonoidReduction[\Boolean\], |
|---|
| 2747 | ReductionWithZeroes[\Boolean,Boolean\] } |
|---|
| 2748 | getter toString() = "AndReduction" |
|---|
| 2749 | empty(): Boolean = true |
|---|
| 2750 | join(a: Boolean, b: Boolean): Boolean = a AND b |
|---|
| 2751 | isZero(a:Boolean): Boolean = NOT a |
|---|
| 2752 | end |
|---|
| 2753 | |
|---|
| 2754 | opr BIG AND[\T\](): BigReduction[\Boolean,Boolean\] = |
|---|
| 2755 | BigReduction[\Boolean,Boolean\](AndReduction) |
|---|
| 2756 | |
|---|
| 2757 | object OrReduction |
|---|
| 2758 | extends { CommutativeMonoidReduction[\Boolean\], |
|---|
| 2759 | ReductionWithZeroes[\Boolean,Boolean\] } |
|---|
| 2760 | getter toString() = "OrReduction" |
|---|
| 2761 | empty(): Boolean = false |
|---|
| 2762 | join(a: Boolean, b: Boolean): Boolean = a OR b |
|---|
| 2763 | isZero(a:Boolean): Boolean = a |
|---|
| 2764 | end |
|---|
| 2765 | |
|---|
| 2766 | opr BIG OR[\T\]():BigReduction[\Boolean, Boolean\] = |
|---|
| 2767 | BigReduction[\Boolean,Boolean\](OrReduction) |
|---|
| 2768 | |
|---|
| 2769 | (** A reduction performing String concatenation **) |
|---|
| 2770 | object StringReduction extends MonoidReduction[\String\] |
|---|
| 2771 | getter toString() = "StringReduction" |
|---|
| 2772 | empty(): String = "" |
|---|
| 2773 | join(a:String, b:String): String = a || b |
|---|
| 2774 | end |
|---|
| 2775 | |
|---|
| 2776 | (** A reduction performing String concatenation with a space **) |
|---|
| 2777 | object SpaceReduction extends MonoidReduction[\String\] |
|---|
| 2778 | getter toString() = "StringReduction" |
|---|
| 2779 | empty(): String = "" |
|---|
| 2780 | join(a:String, b:String): String = a ||| b |
|---|
| 2781 | end |
|---|
| 2782 | |
|---|
| 2783 | (** A reduction performing String concatenation with newline separation **) |
|---|
| 2784 | object NewlineReduction extends AssociativeReduction[\String\] |
|---|
| 2785 | getter toString() = "NewlineReduction" |
|---|
| 2786 | simpleJoin(a, b) = a // b |
|---|
| 2787 | end |
|---|
| 2788 | |
|---|
| 2789 | (** This operator performs string concatenation, first converting |
|---|
| 2790 | its inputs (of type Any) to String if necessary. **) |
|---|
| 2791 | opr BIG ||(): Comprehension[\Any,String,String,String\] = |
|---|
| 2792 | Comprehension[\Any,String,String,String\]( |
|---|
| 2793 | identity[\String\],StringReduction,fn (x:Any)=> "" x) |
|---|
| 2794 | |
|---|
| 2795 | (** This operator performs string concatenation, first converting |
|---|
| 2796 | its inputs (of type Any) to String if necessary, and separating |
|---|
| 2797 | non-empty components by a space. **) |
|---|
| 2798 | opr BIG |||(): Comprehension[\Any,String,String,String\] = |
|---|
| 2799 | Comprehension[\Any,String,String,String\]( |
|---|
| 2800 | identity[\String\],SpaceReduction,fn (x:Any)=> "" x) |
|---|
| 2801 | |
|---|
| 2802 | (** This operator performs string concatenation with newline |
|---|
| 2803 | separation, first converting its inputs (of type Any) to String if |
|---|
| 2804 | necessary. **) |
|---|
| 2805 | opr BIG //(): Comprehension[\Any,String,String,AnyMaybe\] = |
|---|
| 2806 | Comprehension[\Any,String,String,AnyMaybe\]( |
|---|
| 2807 | fn x => x,NewlineReduction,fn (x:Any)=> "" x) |
|---|
| 2808 | |
|---|
| 2809 | (** A %MapReduceReduction% takes an associative binary function %j% on |
|---|
| 2810 | arguments of type %R%, and the identity of that function %z%, and |
|---|
| 2811 | returns the corresponding reduction. **) |
|---|
| 2812 | object MapReduceReduction[\R\](j:(R,R)->R, z:R) extends MonoidReduction[\R\] |
|---|
| 2813 | getter toString()="mapReduceReduction" |
|---|
| 2814 | empty(): R = z |
|---|
| 2815 | join(a:R, b:R): R = (j)(a,b) |
|---|
| 2816 | end |
|---|
| 2817 | |
|---|
| 2818 | (** A %MIMapReduceReduction% takes an associative binary function %j% on |
|---|
| 2819 | arguments of type %R%, and the identity of that function %z%, and |
|---|
| 2820 | returns the corresponding reduction. **) |
|---|
| 2821 | object MIMapReduceReduction[\R\](j:(Any,Any)->R, z:Any) extends MonoidReduction[\Any\] |
|---|
| 2822 | getter toString():String="MIMapReduceReduction from embiggen" |
|---|
| 2823 | empty(): R = z |
|---|
| 2824 | join(a:Any, b:Any): R = (j)(a,b) |
|---|
| 2825 | end |
|---|
| 2826 | |
|---|
| 2827 | (** %embiggen% takes a type %T% and an operation (either an operator |
|---|
| 2828 | %OP% or binary function %f% on type %T%), along with the identity |
|---|
| 2829 | %z% of the operation, and returns a function suitable as the right-hand |
|---|
| 2830 | side of the definition of the corresponding BIG operator. **) |
|---|
| 2831 | (* |
|---|
| 2832 | embiggen[\T,opr OP\](z:Any, g:(Reduction[\Any\],T->Any) -> Any) : T = |
|---|
| 2833 | g(MIOprReduction[\T,OP\](z), fn (x) => x) |
|---|
| 2834 | *) |
|---|
| 2835 | embiggen[\T\](j:(Any,Any)->T, z:T) : Comprehension[\T,T,Any,Any\] = |
|---|
| 2836 | Comprehension[\T,T,Any,Any\](fn (x) => x, MIMapReduceReduction[\T\](j,z), fn (x) => x) |
|---|
| 2837 | |
|---|
| 2838 | (** Helpers for maps and cross products of generators. These can be |
|---|
| 2839 | quite a bit more sophisticated (for example, we can hoist maps |
|---|
| 2840 | outwards if we think that'd be useful), but let's get this much |
|---|
| 2841 | working first. *) |
|---|
| 2842 | trait SomeMappedGenerator[\F\] extends Generator[\F\] end |
|---|
| 2843 | |
|---|
| 2844 | trait MappedGenerator[\E,F\] extends SomeMappedGenerator[\F\] |
|---|
| 2845 | getter g(): Generator[\E\] |
|---|
| 2846 | getter f(): E -> F |
|---|
| 2847 | getter toString(): String = g() ".map(f)" |
|---|
| 2848 | generate[\R\](r: Reduction[\R\], m: F->R): R = |
|---|
| 2849 | g().generate[\R\](r, m COMPOSE f()) |
|---|
| 2850 | reduce(r: Reduction[\F\]): F = |
|---|
| 2851 | g().generate[\F\](r, f()) |
|---|
| 2852 | map[\G\](f': F->G): SimpleMappedGenerator[\E,G\] = |
|---|
| 2853 | SimpleMappedGenerator[\E,G\](g(), f' COMPOSE f()) |
|---|
| 2854 | seq(self) = SimpleMappedSeqGenerator[\E,F\](seq(g()),f()) |
|---|
| 2855 | end |
|---|
| 2856 | |
|---|
| 2857 | object SimpleMappedGenerator[\E,F\](g0: Generator[\E\], f0: E->F) |
|---|
| 2858 | extends MappedGenerator[\E,F\] |
|---|
| 2859 | getter g() = g0 |
|---|
| 2860 | getter f() = f0 |
|---|
| 2861 | end |
|---|
| 2862 | |
|---|
| 2863 | object SimpleMappedIndexed[\E,F,I\](g0: Indexed[\E,I\], f0: E->F) |
|---|
| 2864 | extends { MappedGenerator[\E,F\], Indexed[\F,I\] } |
|---|
| 2865 | getter size(): ZZ32 = |g()| |
|---|
| 2866 | getter g() = g0 |
|---|
| 2867 | getter f() = f0 |
|---|
| 2868 | getter bounds(): Range[\I\] = g().bounds |
|---|
| 2869 | getter indexValuePairs(): Indexed[\(I,F),I\] = |
|---|
| 2870 | g().indexValuePairs.map[\(I,F)\](fn (i:I, e:E): F => (i,(f())(e))) |
|---|
| 2871 | getter indices(): Indexed[\I,I\] = g().indices |
|---|
| 2872 | opr |self| : ZZ32 = |g()| |
|---|
| 2873 | opr[i:I] : F = (f())(g()[i]) |
|---|
| 2874 | opr[r:Range[\I\]] : Indexed[\F,I\] = |
|---|
| 2875 | SimpleMappedIndexed[\E,F,I\](g()[r],f()) |
|---|
| 2876 | |
|---|
| 2877 | ivmap[\R\](ff:(I,F)->R): Indexed[\R,I\] = |
|---|
| 2878 | g0().ivmap[\R\](fn (i:I, e:E) => ff(i, (f())(e))) |
|---|
| 2879 | map[\G\](f': F->G): SimpleMappedIndexed[\E,G,I\] = |
|---|
| 2880 | SimpleMappedIndexed[\E,G,I\](g(), f' COMPOSE f()) |
|---|
| 2881 | end |
|---|
| 2882 | |
|---|
| 2883 | object SimpleMappedSeqGenerator[\E,F\](g0: SequentialGenerator[\E\], f0: E->F) |
|---|
| 2884 | extends { MappedGenerator[\E,F\], SequentialGenerator[\F\] } |
|---|
| 2885 | getter g() = g0 |
|---|
| 2886 | getter f() = f0 |
|---|
| 2887 | getter toString() = "seq(" g0 ".map(f))" |
|---|
| 2888 | seq(self): SimpleMappedSeqGenerator[\E,F\] = self |
|---|
| 2889 | end |
|---|
| 2890 | |
|---|
| 2891 | trait FilterGenerator[\E\] extends Generator[\E\] |
|---|
| 2892 | getter g(): Generator[\E\] |
|---|
| 2893 | getter p(): E -> Condition[\()\] |
|---|
| 2894 | getter toString(): String = g() ".filter(p)" |
|---|
| 2895 | generate[\R\](r:Reduction[\R\], m: E->R): R = |
|---|
| 2896 | g().generate[\R\](r, fn(e:E):R => if (p())(e).holds then m(e) else r.empty() end) |
|---|
| 2897 | reduce(r: Reduction[\E\]): E = |
|---|
| 2898 | g().generate[\E\](r, fn(e:E):E => if (p())(e).holds then e else r.empty() end) |
|---|
| 2899 | filter(p': E -> Condition[\()\]): SimpleFilterGenerator[\E\] = |
|---|
| 2900 | SimpleFilterGenerator[\E\](g(), p() ANDCOND p') |
|---|
| 2901 | seq(self) = SimpleSeqFilterGenerator[\E\](seq(g()),p()) |
|---|
| 2902 | end |
|---|
| 2903 | |
|---|
| 2904 | object SimpleFilterGenerator[\E\](g0:Generator[\E\], p0: E->Condition[\()\]) |
|---|
| 2905 | extends FilterGenerator[\E\] |
|---|
| 2906 | getter g(): Generator[\E\] = g0 |
|---|
| 2907 | getter p(): E -> Condition[\()\] = p0 |
|---|
| 2908 | end |
|---|
| 2909 | |
|---|
| 2910 | object SimpleSeqFilterGenerator[\E\](g0: SequentialGenerator[\E\], p0: E->Condition[\()\]) |
|---|
| 2911 | extends { FilterGenerator[\E\], SequentialGenerator[\E\] } |
|---|
| 2912 | getter g(): Generator[\E\] = g0 |
|---|
| 2913 | getter p(): E -> Condition[\()\] = p0 |
|---|
| 2914 | getter toString() = "seq(" g0 ".filter(p))" |
|---|
| 2915 | seq(self): SimpleSeqFilterGenerator[\E\] = self |
|---|
| 2916 | end |
|---|
| 2917 | |
|---|
| 2918 | trait NestedGenerator[\E,F\] extends Generator[\F\] |
|---|
| 2919 | getter g(): Generator[\E\] |
|---|
| 2920 | getter f(): E -> Generator[\F\] |
|---|
| 2921 | getter toString(): String |
|---|
| 2922 | generate[\R\](r: Reduction[\R\], m: F->R): R = |
|---|
| 2923 | g().generate[\R\](r,fn (e:E):R => (f())(e).generate[\R\](r,m)) |
|---|
| 2924 | mapReduce[\R\](body: F->R, join:(R,R)->R, id:R): R = |
|---|
| 2925 | g().mapReduce[\R\]( |
|---|
| 2926 | fn (e:E): R => (f())(e).mapReduce[\R\](body,join,id), |
|---|
| 2927 | join, id) |
|---|
| 2928 | reduce(r: Reduction[\F\]): F = |
|---|
| 2929 | g().generate[\F\](r,fn (e:E):F => (f())(e).reduce(r)) |
|---|
| 2930 | reduce(j:(F,F)->F, z:F):F = |
|---|
| 2931 | g().mapReduce[\F\](fn (e:E): F => (f())(e).reduce(j,z), j, z) |
|---|
| 2932 | loop(body:F->()): () = |
|---|
| 2933 | g().loop(fn (e:E) => (f())(e).loop(body)) |
|---|
| 2934 | map[\G\](h:F->G): Generator[\G\] = |
|---|
| 2935 | g().nest[\G\](fn (e:E): Generator[\G\] => (f())(e).map[\G\](h)) |
|---|
| 2936 | nest[\G\](h:F->Generator[\G\]): Generator[\G\] = |
|---|
| 2937 | g().nest[\G\](fn (e:E):Generator[\G\] => (f())(e).nest[\G\](h)) |
|---|
| 2938 | end |
|---|
| 2939 | |
|---|
| 2940 | object SimpleNestedGenerator[\E,F\](g0: Generator[\E\], f0: E->Generator[\F\]) |
|---|
| 2941 | extends { NestedGenerator[\E,F\] } |
|---|
| 2942 | getter g() = g0 |
|---|
| 2943 | getter f() = f0 |
|---|
| 2944 | getter toString() = g() ".nest(f)" |
|---|
| 2945 | seq(self) = |
|---|
| 2946 | typecase ff = f() of |
|---|
| 2947 | (E -> SequentialGenerator[\F\]) => |
|---|
| 2948 | SimpleNestedSeqGenerator[\E,F\](seq(g()),ff) |
|---|
| 2949 | else => |
|---|
| 2950 | SimpleNestedSeqGenerator[\E,F\](seq(g()), |
|---|
| 2951 | fn (e:E): SequentialGenerator[\F\] => seq(self.f()(e))) |
|---|
| 2952 | end |
|---|
| 2953 | end |
|---|
| 2954 | |
|---|
| 2955 | object SimpleNestedSeqGenerator[\E,F\] |
|---|
| 2956 | (g0: SequentialGenerator[\E\], f0: E->SequentialGenerator[\F\]) |
|---|
| 2957 | extends { NestedGenerator[\E,F\], SequentialGenerator[\F\] } |
|---|
| 2958 | getter g() = g0 |
|---|
| 2959 | getter f() = f0 |
|---|
| 2960 | getter toString() = "seq(" g() ".nest(f))" |
|---|
| 2961 | end |
|---|
| 2962 | |
|---|
| 2963 | trait PairGenerator[\E,F\] extends Generator[\(E,F)\] |
|---|
| 2964 | comprises { SimplePairGenerator[\E,F\], SimplePairSeqGenerator[\E,F\] } |
|---|
| 2965 | getter e(): Generator[\E\] |
|---|
| 2966 | getter f(): Generator[\F\] |
|---|
| 2967 | getter toString(): String |
|---|
| 2968 | getter size():ZZ32 = |self| |
|---|
| 2969 | opr |self| : ZZ32 = |e()| |f()| |
|---|
| 2970 | generate[\R\](r: Reduction[\R\], m:(E,F)->R): R = |
|---|
| 2971 | e().generate[\R\](r, fn (a: E): R => |
|---|
| 2972 | f().generate[\R\](r, fn (b: F): R => m(a,b))) |
|---|
| 2973 | end |
|---|
| 2974 | |
|---|
| 2975 | object SimplePairGenerator[\E,F\](e0: Generator[\E\], f0: Generator[\F\]) |
|---|
| 2976 | extends PairGenerator[\E,F\] |
|---|
| 2977 | getter e() = e0 |
|---|
| 2978 | getter f() = f0 |
|---|
| 2979 | getter toString()=(e0 ".cross(" f0 ")" ) |
|---|
| 2980 | seq(self) = SimplePairSeqGenerator[\E,F\](seq(e0),seq(f0)) |
|---|
| 2981 | end |
|---|
| 2982 | |
|---|
| 2983 | object SimplePairSeqGenerator[\E,F\](e0: Generator[\E\], f0: Generator[\F\]) |
|---|
| 2984 | extends { PairGenerator[\E,F\], SequentialGenerator[\(E,F)\] } |
|---|
| 2985 | getter e() = e0 |
|---|
| 2986 | getter f() = f0 |
|---|
| 2987 | getter toString()=("seq(" e ".cross(" f "))" ) |
|---|
| 2988 | end |
|---|
| 2989 | |
|---|
| 2990 | (** Helper for serializing generators naively. This code should make |
|---|
| 2991 | * obvious that naive seq is *VERY INEFFICIENT*. It |
|---|
| 2992 | * constructs a function closure whose size is proportional to |
|---|
| 2993 | * %|g|%, and then executes that closure. This trick is old hat |
|---|
| 2994 | * to lambda-calculus wonks, but pretty unfamiliar to the common man. |
|---|
| 2995 | * |
|---|
| 2996 | * Basically each element takes in the accumulated value a from the element |
|---|
| 2997 | * to its left. This is joined with the result of mapping on the |
|---|
| 2998 | * current element value, and that result is returned. Join simply |
|---|
| 2999 | * reverse-composes the functions for its subtrees, so the output of the left |
|---|
| 3000 | * subtree is fed to the right subtree. |
|---|
| 3001 | * |
|---|
| 3002 | * Note that a similar trick can be used to reverse and sequentialize |
|---|
| 3003 | * a generator (use forward function composition rather than reverse |
|---|
| 3004 | * composition, and flipping around the join at the leaves). *) |
|---|
| 3005 | object NaiveSeqGenerator[\E\](g: Generator[\E\]) |
|---|
| 3006 | extends SequentialGenerator[\E\] |
|---|
| 3007 | getter size() = |g| |
|---|
| 3008 | getter toString():String = "naive seq(" g.toString ")" |
|---|
| 3009 | opr |self| : ZZ32 = |g| |
|---|
| 3010 | generate[\R\](r: Reduction[\R\], m:E->R): R = do |
|---|
| 3011 | rcompose(f:R->R, f':R->R): R->R = fn (x:R):R => f'(f(x)) |
|---|
| 3012 | id(x:R):R = x |
|---|
| 3013 | mp(x:E):R->R = fn (a:R):R => r.join(a,m(x)) |
|---|
| 3014 | f : R -> R = g.mapReduce[\R->R\](mp,rcompose,id) |
|---|
| 3015 | mt : R = r.empty() |
|---|
| 3016 | f mt |
|---|
| 3017 | end |
|---|
| 3018 | end |
|---|
| 3019 | |
|---|
| 3020 | (************************************************************ |
|---|
| 3021 | * Ranges |
|---|
| 3022 | ************************************************************) |
|---|
| 3023 | |
|---|
| 3024 | (** Ranges in general represent uses of the # and : operators. |
|---|
| 3025 | It's mostly subtypes of Range that are interesting. |
|---|
| 3026 | |
|---|
| 3027 | The partial order on ranges describes containment: |
|---|
| 3028 | a < b iff all points in a are strictly contained in b. |
|---|
| 3029 | **) |
|---|
| 3030 | trait Range[\T\] |
|---|
| 3031 | extends StandardPartialOrder[\Range[\T\]\] |
|---|
| 3032 | comprises { RangeWithLower[\T\], RangeWithUpper[\T\], |
|---|
| 3033 | RangeWithExtent[\T\], PartialRange[\T\] } |
|---|
| 3034 | excludes { Number } |
|---|
| 3035 | |
|---|
| 3036 | opr[r:Range[\T\]]: Range[\T\] = fail("Unrecognized Range " r) |
|---|
| 3037 | opr[_:OpenRange[\Any\]] : Range[\T\] = self |
|---|
| 3038 | opr[other:LowerRange[\T\]] : Range[\T\] |
|---|
| 3039 | opr[other:UpperRange[\T\]] : Range[\T\] |
|---|
| 3040 | opr[other:ExtentRange[\T\]] : Range[\T\] |
|---|
| 3041 | opr[other:CompleteRange[\T\]] : CompleteRange[\T\] |
|---|
| 3042 | opr =(self,_:Range[\T\]): Boolean = false |
|---|
| 3043 | end |
|---|
| 3044 | |
|---|
| 3045 | trait PartialRange[\T\] extends Range[\T\] |
|---|
| 3046 | comprises { OpenRange[\T\], |
|---|
| 3047 | LowerRange[\T\], UpperRange[\T\], ExtentRange[\T\] } |
|---|
| 3048 | excludes { CompleteRange[\T\] } |
|---|
| 3049 | end |
|---|
| 3050 | |
|---|
| 3051 | object OpenRange[\T\] extends { Range[\T\], PartialRange[\T\] } |
|---|
| 3052 | toString():String = "#" |
|---|
| 3053 | opr[_:OpenRange[\T\]] : OpenRange[\T\] = self |
|---|
| 3054 | |
|---|
| 3055 | opr[other:LowerRange[\T\]] : LowerRange[\T\] = other |
|---|
| 3056 | opr[other:UpperRange[\T\]] : UpperRange[\T\] = other |
|---|
| 3057 | opr[other:ExtentRange[\T\]] : ExtentRange[\T\] = other |
|---|
| 3058 | opr[other:CompleteRange[\T\]] : CompleteRange[\T\] = other |
|---|
| 3059 | opr =(self,_:OpenRange[\T\]): Boolean = true |
|---|
| 3060 | opr CMP(self,other:Range[\T\]): TotalComparison = |
|---|
| 3061 | typecase other of |
|---|
| 3062 | OpenRange[\T\] => EqualTo |
|---|
| 3063 | else => GreaterThan |
|---|
| 3064 | end |
|---|
| 3065 | end |
|---|
| 3066 | |
|---|
| 3067 | opr PARTIAL_LEXICO(a:Comparison, b:Comparison) = |
|---|
| 3068 | typecase a of |
|---|
| 3069 | Unordered => Unordered |
|---|
| 3070 | EqualTo => b |
|---|
| 3071 | else => |
|---|
| 3072 | typecase b of |
|---|
| 3073 | Unordered => Unordered |
|---|
| 3074 | else => a |
|---|
| 3075 | end |
|---|
| 3076 | end |
|---|
| 3077 | |
|---|
| 3078 | opr PARTIAL_LEXICO(a:Comparison, b:()->Comparison) = |
|---|
| 3079 | typecase a of |
|---|
| 3080 | Unordered => Unordered |
|---|
| 3081 | EqualTo => b() |
|---|
| 3082 | else => |
|---|
| 3083 | typecase _ = b() of |
|---|
| 3084 | Unordered => Unordered |
|---|
| 3085 | else => a |
|---|
| 3086 | end |
|---|
| 3087 | end |
|---|
| 3088 | |
|---|
| 3089 | (** Non-traditional partial ordering on tuples, CMP ordering elsewhere. **) |
|---|
| 3090 | opr PCMP[\A,B\](t1:(A,B), t2:(A,B)): Comparison = do |
|---|
| 3091 | (a1,b1)=t1 |
|---|
| 3092 | (a2,b2)=t2 |
|---|
| 3093 | (a1 CMP a2) PARTIAL_LEXICO: (b1 CMP b2) |
|---|
| 3094 | end |
|---|
| 3095 | |
|---|
| 3096 | opr PCMP[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Comparison = do |
|---|
| 3097 | (a1,b1,c1)=t1 |
|---|
| 3098 | (a2,b2,c2)=t2 |
|---|
| 3099 | (a1 CMP a2) PARTIAL_LEXICO: (b1 CMP b2) PARTIAL_LEXICO (c1 CMP c2) |
|---|
| 3100 | end |
|---|
| 3101 | |
|---|
| 3102 | opr PCMP(a:Number, b:Number): TotalComparison = a CMP b |
|---|
| 3103 | |
|---|
| 3104 | (** Non-traditional subtraction of bounds, elementwise on tuples **) |
|---|
| 3105 | opr SUBTR[\A,B\](t1:(A,B), t2:(A,B)): (A,B) = do |
|---|
| 3106 | (a1,b1) = t1 |
|---|
| 3107 | (a2,b2) = t2 |
|---|
| 3108 | (a1 SUBTR a2, b1 SUBTR b2) |
|---|
| 3109 | end |
|---|
| 3110 | |
|---|
| 3111 | opr SUBTR[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): (A,B,C) = do |
|---|
| 3112 | (a1,b1,c1) = t1 |
|---|
| 3113 | (a2,b2,c2) = t2 |
|---|
| 3114 | (a1 SUBTR a2, b1 SUBTR b2, c1 SUBTR c2) |
|---|
| 3115 | end |
|---|
| 3116 | |
|---|
| 3117 | opr SUBTR[\T extends MultiplicativeRing[\T\]\](a:T, b:T):T = a.one + a - b |
|---|
| 3118 | |
|---|
| 3119 | (** join upper and lower bounds comparisons (total or partial) to |
|---|
| 3120 | yield partial containment. **) |
|---|
| 3121 | |
|---|
| 3122 | trait RangeWithLower[\T\] extends Range[\T\] |
|---|
| 3123 | comprises { LowerRange[\T\], CompleteRange[\T\] } |
|---|
| 3124 | getter lower():T |
|---|
| 3125 | end |
|---|
| 3126 | |
|---|
| 3127 | rangeBoundError[\T\](r1:Range[\T\], r2: Range[\T\]): Range[\T\] = |
|---|
| 3128 | fail(r1 "[" r2 "] does not contain bound of indexing range") |
|---|
| 3129 | |
|---|
| 3130 | object LowerRange[\T\](lo:T) extends { RangeWithLower[\T\], PartialRange[\T\] } |
|---|
| 3131 | getter lower():T = lo |
|---|
| 3132 | toString():String = lower() "#" |
|---|
| 3133 | opr[_:OpenRange[\T\]] : LowerRange[\T\] = self |
|---|
| 3134 | opr[other:LowerRange[\T\]] : LowerRange[\T\] = |
|---|
| 3135 | if other.lower >= self.lower then |
|---|
| 3136 | other |
|---|
| 3137 | else |
|---|
| 3138 | rangeBoundError[\T\](self,other) |
|---|
| 3139 | end |
|---|
| 3140 | opr[other:ExtentRange[\T\]] : FullRange[\T,true\] = self.lower # other.extent() |
|---|
| 3141 | opr[other:UpperRange[\T\]] : FullRange[\T,true\] = |
|---|
| 3142 | if other.upper >= self.lower then |
|---|
| 3143 | self.lower : other.upper |
|---|
| 3144 | else |
|---|
| 3145 | rangeBoundError[\T\](self,other) |
|---|
| 3146 | end |
|---|
| 3147 | opr[other:CompleteRange[\T\]] : CompleteRange[\T\] = |
|---|
| 3148 | if other.lower >= self.lower then |
|---|
| 3149 | other |
|---|
| 3150 | else |
|---|
| 3151 | rangeBoundError[\T\](self,other) |
|---|
| 3152 | end |
|---|
| 3153 | opr =(self, x:LowerRange[\T\]): Boolean = self.lower = x.lower |
|---|
| 3154 | opr CMP(self, other:Range[\T\]): Comparison = |
|---|
| 3155 | typecase other of |
|---|
| 3156 | OpenRange[\T\] => LessThan |
|---|
| 3157 | LowerRange[\T\] => other.lower PCMP self.lower |
|---|
| 3158 | CompleteRange[\T\] => |
|---|
| 3159 | typecase c = other.lower PCMP self.lower of |
|---|
| 3160 | EqualTo => GreaterThan |
|---|
| 3161 | LessThan => Unordered |
|---|
| 3162 | else => c |
|---|
| 3163 | end |
|---|
| 3164 | else => Unordered |
|---|
| 3165 | end |
|---|
| 3166 | end |
|---|
| 3167 | |
|---|
| 3168 | trait RangeWithUpper[\T\] extends Range[\T\] |
|---|
| 3169 | comprises { UpperRange[\T\], CompleteRange[\T\] } |
|---|
| 3170 | getter upper():T |
|---|
| 3171 | end |
|---|
| 3172 | |
|---|
| 3173 | object UpperRange[\T\](up:T) extends { RangeWithUpper[\T\], PartialRange[\T\] } |
|---|
| 3174 | getter upper():T = up |
|---|
| 3175 | toString():String = ":" upper() |
|---|
| 3176 | opr[_:OpenRange[\T\]] : UpperRange[\T\] = self |
|---|
| 3177 | opr[other:LowerRange[\T\]] : FullRange[\T,true\] = other.lower:self:upper |
|---|
| 3178 | opr[other:UpperRange[\T\]] : UpperRange[\T\] = |
|---|
| 3179 | if other.upper <= self.upper then |
|---|
| 3180 | other |
|---|
| 3181 | else |
|---|
| 3182 | rangeBoundError[\T\](self,other) |
|---|
| 3183 | end |
|---|
| 3184 | opr[other:ExtentRange[\T\]] : FullRange[\T,true\] = |
|---|
| 3185 | (self.upper SUBTR other.extent) # other.extent |
|---|
| 3186 | opr[other:CompleteRange[\T\]] : CompleteRange[\T\] = |
|---|
| 3187 | if other.upper <= self.upper then |
|---|
| 3188 | other |
|---|
| 3189 | else |
|---|
| 3190 | rangeBoundError[\T\](self,other) |
|---|
| 3191 | end |
|---|
| 3192 | opr =(self,x:UpperRange[\T\]): Boolean = upper() = x.upper() |
|---|
| 3193 | opr CMP(self, other:Range[\T\]): Comparison = |
|---|
| 3194 | typecase other of |
|---|
| 3195 | OpenRange[\T\] => LessThan |
|---|
| 3196 | UpperRange[\T\] => self.upper PCMP other.upper |
|---|
| 3197 | CompleteRange[\T\] => |
|---|
| 3198 | typecase c = self.upper PCMP other.upper of |
|---|
| 3199 | EqualTo => GreaterThan |
|---|
| 3200 | LessThan => Unordered |
|---|
| 3201 | else => c |
|---|
| 3202 | end |
|---|
| 3203 | else => Unordered |
|---|
| 3204 | end |
|---|
| 3205 | end |
|---|
| 3206 | |
|---|
| 3207 | trait RangeWithExtent[\T\] extends Range[\T\] |
|---|
| 3208 | comprises { ExtentRange[\T\], CompleteRange[\T\] } |
|---|
| 3209 | getter extent():T |
|---|
| 3210 | toString():String = "#" self.extent |
|---|
| 3211 | end |
|---|
| 3212 | |
|---|
| 3213 | object ExtentRange[\T\](ex:T) extends { RangeWithExtent[\T\], PartialRange[\T\] } |
|---|
| 3214 | getter extent():T = ex |
|---|
| 3215 | opr[_:OpenRange[\T\]] : ExtentRange[\T\] = self |
|---|
| 3216 | opr[other:LowerRange[\T\]] : FullRange[\T,true\] = other.lower # self.extent |
|---|
| 3217 | opr[other:UpperRange[\T\]] : FullRange[\T,true\] = |
|---|
| 3218 | (other.upper SUBTR self.extent) # self.extent |
|---|
| 3219 | opr[other:ExtentRange[\T\]] : ExtentRange[\T\] = |
|---|
| 3220 | if other.extent <= self.extent then |
|---|
| 3221 | other |
|---|
| 3222 | else |
|---|
| 3223 | rangeBoundError[\T\](self,other) |
|---|
| 3224 | end |
|---|
| 3225 | opr[other:CompleteRange[\T\]] : CompleteRange[\T\] = |
|---|
| 3226 | if other.extent <= self.extent then |
|---|
| 3227 | other |
|---|
| 3228 | else |
|---|
| 3229 | rangeBoundError[\T\](self,other) |
|---|
| 3230 | end |
|---|
| 3231 | opr =(self,x:ExtentRange[\T\]): Boolean = self.extent = x.extent |
|---|
| 3232 | opr CMP(self, other:Range[\T\]): Comparison = |
|---|
| 3233 | typecase other of |
|---|
| 3234 | OpenRange[\T\] => LessThan |
|---|
| 3235 | ExtentRange[\T\] => self.extent PCMP other.extent |
|---|
| 3236 | else => Unordered |
|---|
| 3237 | end |
|---|
| 3238 | end |
|---|
| 3239 | |
|---|
| 3240 | (** The type %CompleteRange[\T\]% is really just %FullRange[\T,flag\]% for |
|---|
| 3241 | either setting of %flag%. We need it for stuff like %typecase% |
|---|
| 3242 | and %extends% clauses since we can't bind universally quantified |
|---|
| 3243 | variables in those settings. Since essentially all the methods are |
|---|
| 3244 | independent of the setting of flag we include them here. **) |
|---|
| 3245 | trait CompleteRange[\T\] |
|---|
| 3246 | extends { RangeWithLower[\T\], RangeWithUpper[\T\], |
|---|
| 3247 | RangeWithExtent[\T\], Indexed[\T,T\] } |
|---|
| 3248 | comprises { FullRange[\T,true\], FullRange[\T,false\] } |
|---|
| 3249 | getter indices(): FullRange[\T,true\] = bounds() |
|---|
| 3250 | getter isBounded(): Boolean |
|---|
| 3251 | getter isSized(): Boolean |
|---|
| 3252 | |
|---|
| 3253 | (** The following two methods are used in bounds checking code to |
|---|
| 3254 | permit ranges that are just outside the edge of the given |
|---|
| 3255 | range. Because they're intended for internal use we ignore |
|---|
| 3256 | the setting of flag and return a CompleteRange. **) |
|---|
| 3257 | widenUpper(): CompleteRange[\T\] |
|---|
| 3258 | widenLower(): CompleteRange[\T\] |
|---|
| 3259 | |
|---|
| 3260 | opr[r:Range[\T\]]: CompleteRange[\T\] = fail("Unrecognized Range " r) |
|---|
| 3261 | opr[_:OpenRange[\T\]]: CompleteRange[\T\] = self |
|---|
| 3262 | (** Square-bracket indexing on a FullRange restricts that range to |
|---|
| 3263 | the range provided. Restriction should behave as follows: |
|---|
| 3264 | - Restriction to an OpenRange is the identity. |
|---|
| 3265 | - An UpperRange or ExtentRange restrict the upper bound and |
|---|
| 3266 | extent of the range. |
|---|
| 3267 | - A LowerRange restricts the lower bound and extent of the range. |
|---|
| 3268 | Note that this makes it compatible with the square-bracket |
|---|
| 3269 | indexing of the Indexed trait. **) |
|---|
| 3270 | opr[r:LowerRange[\T\]]: CompleteRange[\T\] = |
|---|
| 3271 | if r.lower = self.lower then |
|---|
| 3272 | (* Important, also handles empty range case. *) |
|---|
| 3273 | self |
|---|
| 3274 | elif r.lower IN widenUpper() then |
|---|
| 3275 | r.lower:self.upper |
|---|
| 3276 | else |
|---|
| 3277 | rangeBoundError[\T\](self,r) |
|---|
| 3278 | end |
|---|
| 3279 | opr[r:UpperRange[\T\]]: CompleteRange[\T\] = |
|---|
| 3280 | if r.upper = self.upper then |
|---|
| 3281 | (* Important, also handles empty range case. *) |
|---|
| 3282 | self |
|---|
| 3283 | elif r.upper IN widenLower() then |
|---|
| 3284 | self.lower:r.upper |
|---|
| 3285 | else |
|---|
| 3286 | rangeBoundError[\T\](self,r) |
|---|
| 3287 | end |
|---|
| 3288 | opr[r:ExtentRange[\T\]]: CompleteRange[\T\] = |
|---|
| 3289 | if r.extent <= self.extent then |
|---|
| 3290 | self.lower#r.extent |
|---|
| 3291 | else |
|---|
| 3292 | fail(self "[" r "] is too small in some dimension") |
|---|
| 3293 | end |
|---|
| 3294 | opr[r:CompleteRange[\T\]]: CompleteRange[\T\] = |
|---|
| 3295 | if r.lower < self.lower then |
|---|
| 3296 | rangeBoundError[\T\](self,r) |
|---|
| 3297 | elif r.upper > self.upper then |
|---|
| 3298 | rangeBoundError[\T\](self,r) |
|---|
| 3299 | else |
|---|
| 3300 | r |
|---|
| 3301 | end |
|---|
| 3302 | |
|---|
| 3303 | toString():String = |
|---|
| 3304 | if self.isBounded then |
|---|
| 3305 | self.lower ":" self.upper |
|---|
| 3306 | else |
|---|
| 3307 | self.lower "#" self.extent |
|---|
| 3308 | end |
|---|
| 3309 | |
|---|
| 3310 | opr =(self, other:CompleteRange[\T\]): Boolean = |
|---|
| 3311 | (* isBounded()=other.isBounded() AND |
|---|
| 3312 | APB 2008.08.20: this seems bogus: isBounded tells us only whether we were created |
|---|
| 3313 | using an extent or an upper bound, and should not effect the comparison *) |
|---|
| 3314 | lower()=other.lower() AND extent() = other.extent() |
|---|
| 3315 | |
|---|
| 3316 | opr CMP(self, other:Range[\T\]): Comparison = |
|---|
| 3317 | typecase other of |
|---|
| 3318 | CompleteRange[\T\] => |
|---|
| 3319 | a = self.lower PCMP other.lower |
|---|
| 3320 | b = self.upper PCMP other.upper |
|---|
| 3321 | typecase _ = (a,b) of |
|---|
| 3322 | (Unordered,Comparison) => Unordered |
|---|
| 3323 | (Comparison,Unordered) => Unordered |
|---|
| 3324 | (LessThan,LessThan) => Unordered |
|---|
| 3325 | (GreaterThan,GreaterThan) => Unordered |
|---|
| 3326 | (* This case seems unncessary; the (EqualTo,Comparison) case will cover us --- APB 2008.08.20 |
|---|
| 3327 | (EqualTo,EqualTo) => EqualTo |
|---|
| 3328 | if self.isBounded = other.isBounded then |
|---|
| 3329 | EqualTo |
|---|
| 3330 | else |
|---|
| 3331 | Unordered |
|---|
| 3332 | end |
|---|
| 3333 | *) |
|---|
| 3334 | (EqualTo,Comparison) => b |
|---|
| 3335 | (GreaterThan,Comparison) => LessThan |
|---|
| 3336 | else (* LessThan,Comparison *) => GreaterThan |
|---|
| 3337 | end |
|---|
| 3338 | else => INVERSE (other CMP self) |
|---|
| 3339 | end |
|---|
| 3340 | end |
|---|
| 3341 | |
|---|
| 3342 | (** A %FullRange% is either bounded (generated from a lower and upper |
|---|
| 3343 | bound, as in %l:u%) or sized (generated from a lower bound and a |
|---|
| 3344 | size, as in %l#s%). These two kinds of range behave identically |
|---|
| 3345 | in most settings; the only time they behave differently is when we |
|---|
| 3346 | construct a strided range: both %l:u:i% and %l#s:i% generate |
|---|
| 3347 | elements %l, l+i, l+2i, ...%, but the former is bounded and |
|---|
| 3348 | generates no element larger than %i% and the latter is sized and |
|---|
| 3349 | generates exactly %s% elements. |
|---|
| 3350 | |
|---|
| 3351 | Data structure bounds are always bounded. **) |
|---|
| 3352 | trait FullRange[\T, bool bounded\] extends CompleteRange[\T\] |
|---|
| 3353 | comprises { ScalarRange[\T,bounded\], TupleRange[\T,bounded\] } |
|---|
| 3354 | getter isBounded(): Boolean = bounded |
|---|
| 3355 | getter isSized(): Boolean = NOT bounded |
|---|
| 3356 | end |
|---|
| 3357 | |
|---|
| 3358 | rangeIndexFailure[\T\](r:CompleteRange[\T\],i:T): () = |
|---|
| 3359 | fail(r "[" i "] out of range.") |
|---|
| 3360 | |
|---|
| 3361 | (** ParRanges and SeqRanges, the simplest and most basic of all |
|---|
| 3362 | generators. They generate |self| numbers, incrementing by 1, |
|---|
| 3363 | starting with lower() (that's the canonical ordering). *) |
|---|
| 3364 | trait ScalarRange[\N extends Integral[\N\], bool bounded\] |
|---|
| 3365 | extends { FullRange[\N, bounded\] } |
|---|
| 3366 | comprises { ParRange[\N, bounded\], SeqRange[\N, bounded\] } |
|---|
| 3367 | getter bounds():FullRange[\N,true\] = ParRange[\N,true\](0,extent()) |
|---|
| 3368 | getter upper():N = lower() + extent() - 1 |
|---|
| 3369 | getter size():ZZ32 = |self| |
|---|
| 3370 | widenUpper(): ScalarRange[\N,false\] = lower()#(extent()+1) |
|---|
| 3371 | widenLower(): ScalarRange[\N,false\] = (lower()-1)#(extent()+1) |
|---|
| 3372 | opr |self| : ZZ32 = narrow(0 MAX extent()) |
|---|
| 3373 | opr[i:N]: N = |
|---|
| 3374 | if 0 <= i < extent() then |
|---|
| 3375 | i + lower() |
|---|
| 3376 | else |
|---|
| 3377 | rangeIndexFailure[\N\](self,i) |
|---|
| 3378 | end |
|---|
| 3379 | opr IN(a:N, self): Boolean = do |
|---|
| 3380 | t = a - lower() |
|---|
| 3381 | 0 <= t < extent() |
|---|
| 3382 | end |
|---|
| 3383 | end |
|---|
| 3384 | |
|---|
| 3385 | value object ParRange[\N extends Integral[\N\], bool bounded\](lo:N, ex:N) |
|---|
| 3386 | extends ScalarRange[\N,bounded\] |
|---|
| 3387 | getter extent() = ex |
|---|
| 3388 | getter lower() = lo |
|---|
| 3389 | getter indexValuePairs() = |
|---|
| 3390 | ParRange[\N,bounded\](0,ex).map[\(N,N)\](fn (n:N):(N,N) => (n,n+lo)) |
|---|
| 3391 | |
|---|
| 3392 | seq(self) = SeqRange[\N,bounded\](lo,ex) |
|---|
| 3393 | generate[\R\](r: Reduction[\R\], m: N->R): R = |
|---|
| 3394 | if ex < 1 then |
|---|
| 3395 | r.empty() |
|---|
| 3396 | else |
|---|
| 3397 | gen(l,s) = if s>=2 then |
|---|
| 3398 | (s1,s2) = partition(s) |
|---|
| 3399 | r.join(gen(l,s1),gen(l+s1,s2)) |
|---|
| 3400 | else |
|---|
| 3401 | m(l) |
|---|
| 3402 | end |
|---|
| 3403 | gen(lo,ex) |
|---|
| 3404 | end |
|---|
| 3405 | mapReduce[\R\](m: N->R, j:(R,R)->R, z:R): R = |
|---|
| 3406 | if ex < 1 then |
|---|
| 3407 | z |
|---|
| 3408 | else |
|---|
| 3409 | gen(l,s) = if s>=2 then |
|---|
| 3410 | (s1,s2) = partition(s) |
|---|
| 3411 | j(gen(l,s1),gen(l+s1,s2)) |
|---|
| 3412 | else |
|---|
| 3413 | m(l) |
|---|
| 3414 | end |
|---|
| 3415 | gen(lo,ex) |
|---|
| 3416 | end |
|---|
| 3417 | reduce(j:(N,N)->N, z:N):N = |
|---|
| 3418 | if ex < 1 then |
|---|
| 3419 | z |
|---|
| 3420 | else |
|---|
| 3421 | gen(l,s) = if s>=2 then |
|---|
| 3422 | (s1,s2) = partition(s) |
|---|
| 3423 | j(gen(l,s1),gen(l+s1,s2)) |
|---|
| 3424 | else |
|---|
| 3425 | l |
|---|
| 3426 | end |
|---|
| 3427 | gen(lo,ex) |
|---|
| 3428 | end |
|---|
| 3429 | reduce(r: Reduction[\N\]):N = |
|---|
| 3430 | if ex < 1 then |
|---|
| 3431 | r.empty() |
|---|
| 3432 | else |
|---|
| 3433 | gen(l,s) = if s>=2 then |
|---|
| 3434 | (s1,s2) = partition(s) |
|---|
| 3435 | r.join(gen(l,s1),gen(l+s1,s2)) |
|---|
| 3436 | else |
|---|
| 3437 | l |
|---|
| 3438 | end |
|---|
| 3439 | gen(lo,ex) |
|---|
| 3440 | end |
|---|
| 3441 | loop(f:N->()): () = |
|---|
| 3442 | if ex < 1 then |
|---|
| 3443 | () |
|---|
| 3444 | else |
|---|
| 3445 | gen(l,s) = if s>=2 then |
|---|
| 3446 | (s1,s2) = partition(s) |
|---|
| 3447 | (gen(l,s1),gen(l+s1,s2)) |
|---|
| 3448 | () |
|---|
| 3449 | else |
|---|
| 3450 | f(l) |
|---|
| 3451 | end |
|---|
| 3452 | gen(lo,ex) |
|---|
| 3453 | end |
|---|
| 3454 | end |
|---|
| 3455 | value object SeqRange[\N extends Integral[\N\], bool bounded\](lo:N, ex:N) |
|---|
| 3456 | extends { ScalarRange[\N,bounded\], SequentialGenerator[\N\] } |
|---|
| 3457 | getter extent() = ex |
|---|
| 3458 | getter lower() = lo |
|---|
| 3459 | getter toString() = |
|---|
| 3460 | ("seq(" lo (if bounded then ":" upper() else "#" ex ")")) |
|---|
| 3461 | getter indexValuePairs() = |
|---|
| 3462 | SeqRange[\N,bounded\](0,ex).map[\(N,N)\](fn (n:N):(N,N) => (n,n+lo)) |
|---|
| 3463 | generate[\R\](r: Reduction[\R\], m: N->R): R = do |
|---|
| 3464 | h = lo + ex |
|---|
| 3465 | l : N := lo |
|---|
| 3466 | acc : R = r.empty() |
|---|
| 3467 | (* DON'T DEFINE THIS USING RECURSION!!! *) |
|---|
| 3468 | while l < h do |
|---|
| 3469 | b = m(l) |
|---|
| 3470 | acc := r.join(acc, b) |
|---|
| 3471 | l += 1 |
|---|
| 3472 | end |
|---|
| 3473 | acc |
|---|
| 3474 | end |
|---|
| 3475 | loop(f: N->()): () = do |
|---|
| 3476 | h = lo + ex |
|---|
| 3477 | l : N := lo |
|---|
| 3478 | (* DON'T DEFINE THIS USING RECURSION!!! *) |
|---|
| 3479 | while l < h do |
|---|
| 3480 | f(l) |
|---|
| 3481 | l += 1 |
|---|
| 3482 | end |
|---|
| 3483 | end |
|---|
| 3484 | end |
|---|
| 3485 | |
|---|
| 3486 | trait TupleRange[\T, bool bounded\] extends FullRange[\T,bounded\] |
|---|
| 3487 | end |
|---|
| 3488 | |
|---|
| 3489 | object Tuple2Range[\N extends Integral[\N\], M extends Integral[\M\], bool bounded\] |
|---|
| 3490 | (l1:N,l2:M,x1:N,x2:M) |
|---|
| 3491 | extends { TupleRange[\(N,M),bounded\], DelegatedIndexed[\(N,M),(N,M)\] } |
|---|
| 3492 | getter bounds():Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](0,0,x1,x2) |
|---|
| 3493 | getter extent():(N,M) = (x1,x2) |
|---|
| 3494 | getter lower():(N,M) = (l1,l2) |
|---|
| 3495 | getter upper():(N,M) = (l1+x1-1, l2+x2-1) |
|---|
| 3496 | getter size():(N,M) = |self| |
|---|
| 3497 | getter generator():Generator[\(N,M)\] = |
|---|
| 3498 | ParRange[\N,bounded\](l1,x1).cross[\M\](ParRange[\M,bounded\](l2,x2)) |
|---|
| 3499 | getter toString(): String = |
|---|
| 3500 | ("(" l1 "," l2 |
|---|
| 3501 | (if bounded then |
|---|
| 3502 | (u1,u2) = upper() |
|---|
| 3503 | "):(" u1 "," u2 ")" |
|---|
| 3504 | else |
|---|
| 3505 | ")#(" x1 "," x2 ")" |
|---|
| 3506 | end)) |
|---|
| 3507 | getter indexValuePairs() = |
|---|
| 3508 | bounds().map[\((N,M),(N,M))\]( |
|---|
| 3509 | fn (n:N,m:M):((N,M),(N,M)) => ((n,m),(n+l1,m+l2))) |
|---|
| 3510 | widenUpper(): Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](l1,l2,x1+1,x2+1) |
|---|
| 3511 | widenLower(): Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](l1-1,l2-1,x1+1,x2+1) |
|---|
| 3512 | opr |self| : ZZ32 = narrow((0 MAX x1) (0 MAX x2)) |
|---|
| 3513 | opr[i:(N,M)]: (N,M) = do |
|---|
| 3514 | (i1,i2) = i |
|---|
| 3515 | if 0 <= i1 < x1 AND 0 <= i2 < x2 then |
|---|
| 3516 | (i1+l1,i2+l2) |
|---|
| 3517 | else |
|---|
| 3518 | rangeIndexFailure[\(N,M)\](self,i) |
|---|
| 3519 | end |
|---|
| 3520 | end |
|---|
| 3521 | opr IN(t:(N,M), self): Boolean = do |
|---|
| 3522 | (v1,v2) = t |
|---|
| 3523 | 0 <= v1-l1 < x1 AND 0 <= v2-l2 < x2 |
|---|
| 3524 | end |
|---|
| 3525 | opr =(self,r:Tuple2Range[\N,M,bounded\]): Boolean = |
|---|
| 3526 | l1=r.l1 AND l2=r.l2 AND x1=r.x1 AND x2=r.x2 |
|---|
| 3527 | end |
|---|
| 3528 | |
|---|
| 3529 | object Tuple3Range[\N1 extends Integral[\N1\], N2 extends Integral[\N2\], N3 extends Integral[\N3\], |
|---|
| 3530 | bool bounded\] |
|---|
| 3531 | (l1:N1,l2:N2,l3:N3,x1:N1,x2:N2,x3:N3) |
|---|
| 3532 | extends { TupleRange[\(N1,N2,N3),bounded\], |
|---|
| 3533 | DelegatedIndexed[\(N1,N2,N3),(N1,N2,N3)\] } |
|---|
| 3534 | getter bounds():Tuple3Range[\N1,N2,N3,true\] = |
|---|
| 3535 | Tuple3Range[\N1,N2,N3,true\]((0,0,0),(x1,x2,x3)) |
|---|
| 3536 | getter extent():(N1,N2,N3) = (x1,x2,x3) |
|---|
| 3537 | getter lower():(N1,N2,N3) = (l1,l2,l3) |
|---|
| 3538 | getter upper():(N1,N2,N3) = (l1+x1-1,l2+x2-1,l3+x3-1) |
|---|
| 3539 | getter size():(N1,N2,N3) = |self| |
|---|
| 3540 | getter generator():Generator[\(N1,N2,N3)\] = |
|---|
| 3541 | ParRange[\N1,bounded\](l1,x1).cross[\N2\](ParRange[\N2,bounded\](l2,x2)).cross[\N3\]( |
|---|
| 3542 | ParRange[\N3,bounded\](l3,x3)).map[\(N1,N2,N3)\]( |
|---|
| 3543 | fn (t:(N1,N2),n3:N3):(N1,N2,N3) => do (n1,n2)=t; (n1,n2,n3) end) |
|---|
| 3544 | getter toString(): String = |
|---|
| 3545 | ("(" l1 "," l2 "," l3 |
|---|
| 3546 | (if bounded then |
|---|
| 3547 | (u1,u2,u3) = upper() |
|---|
| 3548 | "):(" u1 "," u2 "," u3 ")" |
|---|
| 3549 | else |
|---|
| 3550 | ")#(" x1 "," x2 "," x3 ")" |
|---|
| 3551 | end)) |
|---|
| 3552 | getter indexValuePairs() = |
|---|
| 3553 | (0#x1).cross(0#x2).cross(0#x3).map[\((N1,N2,N3),(N1,N2,N3))\]( |
|---|
| 3554 | fn (t:(N1,N2),n3:N3):((N1,N2,N3),(N1,N2,N3)) => |
|---|
| 3555 | do (n1,n2)=t; ((n1,n2,n3),(n1+l1,n2+l2,n3+l3)) end) |
|---|
| 3556 | widenUpper(): Tuple3Range[\N1,N2,N3,true\] = |
|---|
| 3557 | Tuple3Range[\N1,N2,N3,true\](l1,l2,l3,x1+1,x2+1,x3+1) |
|---|
| 3558 | widenLower(): Tuple3Range[\N1,N2,N3,true\] = |
|---|
| 3559 | Tuple3Range[\N1,N2,N3,true\](l1-1,l2-1,l3-1,x1+1,x2+1,x3+1) |
|---|
| 3560 | opr |self| : (N1,N2,N3) = narrow((0 MAX x1) (0 MAX x2) (0 MAX x3)) |
|---|
| 3561 | opr[i:(N1,N2,N3)]: (N1,N2,N3) = do |
|---|
| 3562 | (i1,i2,i3) = i |
|---|
| 3563 | if 0 <= i1 < x1 AND 0 <= i2 < x2 AND 0 <= i3 < x3 then |
|---|
| 3564 | (i1+l1,i2+l2,i3+l3) |
|---|
| 3565 | else |
|---|
| 3566 | rangeIndexFailure[\(N1,N2,N3)\](self,i) |
|---|
| 3567 | end |
|---|
| 3568 | end |
|---|
| 3569 | opr IN(t:(N1,N2,N3), self): Boolean = do |
|---|
| 3570 | (v1,v2,v3) = t |
|---|
| 3571 | 0 <= v1-l1 < x1 AND 0 <= v2-l2 < x2 AND 0 <= v3-l3 < x3 |
|---|
| 3572 | end |
|---|
| 3573 | opr =(self,r:Tuple3Range[\N1,N2,N3,bounded\]): Boolean = |
|---|
| 3574 | l1=r.l1 AND l2=r.l2 AND x1=r.x1 AND x2=r.x2 AND l3=r.l3 AND x3=r.x3 |
|---|
| 3575 | end |
|---|
| 3576 | |
|---|
| 3577 | (** Helpers for # to get the type instantiation "right". We pass in bogus ZZ32's to |
|---|
| 3578 | ensure that the result type is at least ZZ32. **) |
|---|
| 3579 | sizedRange[\I extends AnyIntegral\](_:I,lo:I,ex:I): ParRange[\I,false\] = ParRange[\I,false\](lo,ex) |
|---|
| 3580 | sized2Range[\I extends AnyIntegral, J extends AnyIntegral\] |
|---|
| 3581 | (_:I,_:J,l1:I,l2:J,ex1:I,ex2:J): Tuple2Range[\I,J,false\] = |
|---|
| 3582 | Tuple2Range[\I,J,false\](l1,l2,ex1,ex2) |
|---|
| 3583 | sized3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3584 | (_:I,_:J,_:K,l1:I,l2:J,l3:K,ex1:I,ex2:J,ex3:K): Tuple3Range[\I,J,K,false\] = |
|---|
| 3585 | Tuple3Range[\I,J,K,false\](l1,l2,l3,ex1,ex2,ex3) |
|---|
| 3586 | |
|---|
| 3587 | (** The # and : operators serve as factories for parallel ranges. **) |
|---|
| 3588 | opr #[\I extends AnyIntegral\](lo:I, ex:I): ParRange[\I,false\] = sizedRange(0 asif ZZ32,lo,ex) |
|---|
| 3589 | (* |
|---|
| 3590 | opr #(lo:IntLiteral, ex:IntLiteral): ParRange[\ZZ32\] = ParRange[\ZZ32,false\](lo,ex) |
|---|
| 3591 | *) |
|---|
| 3592 | opr #[\I extends AnyIntegral, J extends AnyIntegral\] |
|---|
| 3593 | (lo:(I,J), ex:(I,J)): Tuple2Range[\I,J,false\] = |
|---|
| 3594 | do (l1,l2)=lo; (x1,x2)=ex; sized2Range(0 asif ZZ32,0 asif ZZ32,l1,l2,x1,x2) end |
|---|
| 3595 | opr #[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3596 | (lo:(I,J,K), ex:(I,J,K)): Tuple3Range[\I,J,K,false\] = |
|---|
| 3597 | do (l1,l2,l3)=lo; (x1,x2,x3)=ex |
|---|
| 3598 | sized3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32,l1,l2,l3,x1,x2,x3) |
|---|
| 3599 | end |
|---|
| 3600 | |
|---|
| 3601 | (** Helpers for : to get the type instantiation "right". We pass in bogus ZZ32's to |
|---|
| 3602 | ensure that the result type is at least ZZ32. **) |
|---|
| 3603 | boundedRange[\I extends AnyIntegral\](_:I,lo:I,ex:I): ParRange[\I,true\] = ParRange[\I,true\](lo,ex) |
|---|
| 3604 | bounded2Range[\I extends AnyIntegral, J extends AnyIntegral\] |
|---|
| 3605 | (_:I,_:J,l1:I,l2:J,ex1:I,ex2:J): Tuple2Range[\I,J,true\] = |
|---|
| 3606 | Tuple2Range[\I,J,true\](l1,l2,ex1,ex2) |
|---|
| 3607 | bounded3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3608 | (_:I,_:J,_:K,l1:I,l2:J,l3:K,ex1:I,ex2:J,ex3:K): Tuple3Range[\I,J,K,true\] = |
|---|
| 3609 | Tuple3Range[\I,J,K,true\](l1,l2,l3,ex1,ex2,ex3) |
|---|
| 3610 | |
|---|
| 3611 | opr :[\I extends AnyIntegral\](lo:I, hi:I): ParRange[\I,true\] = |
|---|
| 3612 | boundedRange(0 asif ZZ32,lo,hi-lo+1) |
|---|
| 3613 | (* |
|---|
| 3614 | opr :(lo:IntLiteral, hi:IntLiteral): ParRange[\ZZ32,true\] = |
|---|
| 3615 | ParRange[\ZZ32,true\](lo,hi-lo+1) |
|---|
| 3616 | *) |
|---|
| 3617 | opr :[\I extends AnyIntegral, J extends AnyIntegral\] |
|---|
| 3618 | (lo:(I,J), hi:(I,J)): Tuple2Range[\I,J,true\] = |
|---|
| 3619 | do (l1,l2)=lo; (h1,h2)=hi; bounded2Range(0 asif ZZ32,0 asif ZZ32,l1,l2,h1-l1+1,h2-l2+1) end |
|---|
| 3620 | opr :[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3621 | (lo:(I,J,K), hi:(I,J,K)): Tuple3Range[\I,J,K,true\] = do |
|---|
| 3622 | (l1,l2,l3)=lo; (h1,h2,h3)=hi |
|---|
| 3623 | bounded3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32,l1,l2,l3,h1-l1+1,h2-l2+1,h3-l3+1) |
|---|
| 3624 | end |
|---|
| 3625 | |
|---|
| 3626 | lowerRange[\I extends AnyIntegral\](_:I,x:I):LowerRange[\I\] = LowerRange[\I\](x) |
|---|
| 3627 | lower2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J): |
|---|
| 3628 | LowerRange[\(I,J)\] = LowerRange[\(I,J)\](x,y) |
|---|
| 3629 | lower3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3630 | (_:I,_:J,_:K,x:I,y:J,z:K): LowerRange[\(I,J,K)\] = |
|---|
| 3631 | LowerRange[\(I,J,K)\](x,y,z) |
|---|
| 3632 | |
|---|
| 3633 | extentRange[\I extends AnyIntegral\](_:I,x:I):ExtentRange[\I\] = ExtentRange[\I\](x) |
|---|
| 3634 | extent2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J): |
|---|
| 3635 | ExtentRange[\(I,J)\] = ExtentRange[\(I,J)\](x,y) |
|---|
| 3636 | extent3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3637 | (_:I,_:J,_:K,x:I,y:J,z:K): ExtentRange[\(I,J,K)\] = |
|---|
| 3638 | ExtentRange[\(I,J,K)\](x,y,z) |
|---|
| 3639 | |
|---|
| 3640 | upperRange[\I extends AnyIntegral\](_:I,x:I):UpperRange[\I\] = UpperRange[\I\](x) |
|---|
| 3641 | upper2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J): |
|---|
| 3642 | UpperRange[\(I,J)\] = UpperRange[\(I,J)\](x,y) |
|---|
| 3643 | upper3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] |
|---|
| 3644 | (_:I,_:J,_:K,x:I,y:J,z:K): UpperRange[\(I,J,K)\] = |
|---|
| 3645 | UpperRange[\(I,J,K)\](x,y,z) |
|---|
| 3646 | |
|---|
| 3647 | (** Factories for incomplete ranges **) |
|---|
| 3648 | opr (x:I)#[\I extends AnyIntegral\] : LowerRange[\I\] = lowerRange(0 asif ZZ32, x) |
|---|
| 3649 | opr (x:I,y:J)#[\I extends AnyIntegral, J extends AnyIntegral\] : LowerRange[\(I,J)\] = |
|---|
| 3650 | lower2Range(0 asif ZZ32,0 asif ZZ32, x,y) |
|---|
| 3651 | opr (x:I,y:J,z:K)#[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] : |
|---|
| 3652 | LowerRange[\(I,J,K)\] = lower3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z) |
|---|
| 3653 | opr (x:I):[\I\] : LowerRange[\I\] = x# |
|---|
| 3654 | opr #[\I extends AnyIntegral\](x:I) : ExtentRange[\I\] = extentRange(0 asif ZZ32, x) |
|---|
| 3655 | opr #[\I extends AnyIntegral, J extends AnyIntegral\](xy:(I,J)) : ExtentRange[\(I,J)\] = |
|---|
| 3656 | do (x,y) = xy; extent2Range(0 asif ZZ32,0 asif ZZ32, x,y) end |
|---|
| 3657 | opr #[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\](xyz:(I,J,K)) : |
|---|
| 3658 | ExtentRange[\(I,J,K)\] = |
|---|
| 3659 | do (x,y,z) = xyz; extent3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z) end |
|---|
| 3660 | opr :[\I extends AnyIntegral\](x:I) : UpperRange[\I\] = upperRange(0 asif ZZ32, x) |
|---|
| 3661 | opr :[\I extends AnyIntegral, J extends AnyIntegral\](xy:(I,J)) : UpperRange[\(I,J)\] = |
|---|
| 3662 | do (x,y) = xy; upper2Range(0 asif ZZ32,0 asif ZZ32, x,y) end |
|---|
| 3663 | opr :[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\](xyz:(I,J,K)) : |
|---|
| 3664 | UpperRange[\(I,J,K)\] = |
|---|
| 3665 | do (x,y,z) = xyz; upper3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z) end |
|---|
| 3666 | (* |
|---|
| 3667 | opr (x:I)#[\I\] : LowerRange[\I\] = LowerRange[\I\](x) |
|---|
| 3668 | opr (x:I):[\I\] : LowerRange[\I\] = LowerRange[\I\](x) |
|---|
| 3669 | opr #[\I\](x:I) : ExtentRange[\I\] = ExtentRange[\I\](x) |
|---|
| 3670 | opr :[\I\](x:I) : UpperRange[\I\] = UpperRange[\I\](x) |
|---|
| 3671 | *) |
|---|
| 3672 | opr #() : OpenRange[\Any\] = OpenRange[\Any\] |
|---|
| 3673 | opr :() : OpenRange[\Any\] = OpenRange[\Any\] |
|---|
| 3674 | |
|---|
| 3675 | trait String extends { StandardTotalOrder[\String\], ZeroIndexed[\Char\], DelegatedIndexed[\Char,ZZ32\] } |
|---|
| 3676 | excludes {Number, Char, AnyMultiplicativeRing, AnyList} |
|---|
| 3677 | getter size() : ZZ32 |
|---|
| 3678 | getter toString() : String = self |
|---|
| 3679 | getter indices() : FullRange[\ZZ32,true\] = self.bounds |
|---|
| 3680 | (* This is the "dumb" generator. It always works, but can be "Big O" inefficient, e.g., for |
|---|
| 3681 | CatString trees. Sub-traits should override it with equivalent but more efficeint code. *) |
|---|
| 3682 | getter generator() : Generator[\Char\] = |
|---|
| 3683 | indices().map[\Char\](fn (i:ZZ32):Char => self[i]) |
|---|
| 3684 | getter depth() = 0 |
|---|
| 3685 | |
|---|
| 3686 | showStructure() = showStructure(0) |
|---|
| 3687 | |
|---|
| 3688 | opr |self| : ZZ32 = self.size |
|---|
| 3689 | |
|---|
| 3690 | opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison = |
|---|
| 3691 | ((BIG LEXICO[i <- 0#(|self| MIN |other|) ] self.get(i) CASE_INSENSITIVE_CMP other.get(i)) LEXICO (|self| CMP |other|)) |
|---|
| 3692 | |
|---|
| 3693 | opr CMP(self, other:String): TotalComparison = |
|---|
| 3694 | ((BIG LEXICO[i <- 0#(|self| MIN |other|) ] self.get(i) CMP other.get(i)) LEXICO (|self| CMP |other|)) |
|---|
| 3695 | |
|---|
| 3696 | opr [i:ZZ32]: Char = |
|---|
| 3697 | (** As a convenience, we permit LowerRange indexing to go 1 past the bounds |
|---|
| 3698 | of the String, returning the empty String, in order to permit some convenient |
|---|
| 3699 | String-trimming idioms. **) |
|---|
| 3700 | if 0 <= i < |self| |
|---|
| 3701 | then self.get(i) |
|---|
| 3702 | else |
|---|
| 3703 | (* println "Index " i " not in bounds " self.bounds *) |
|---|
| 3704 | throw IndexOutOfBounds(0,(|self|)-1,i) |
|---|
| 3705 | end |
|---|
| 3706 | |
|---|
| 3707 | opr[r0:Range[\ZZ32\]] : String = do |
|---|
| 3708 | r1 = self.bounds[r0] (* This will complete r0 if it is incomplete, and throw a bounds exception when necessary *) |
|---|
| 3709 | self.uncheckedSubstring(r1) |
|---|
| 3710 | end |
|---|
| 3711 | |
|---|
| 3712 | (** The operator %||% with at least one String argument converts to String and |
|---|
| 3713 | appends **) |
|---|
| 3714 | opr ||(self, b:String):String |
|---|
| 3715 | opr ||(self, b:Number):String = self || b.toString |
|---|
| 3716 | opr ||(self, c:Char):String |
|---|
| 3717 | opr ||(self, b:()):String = self || "()" |
|---|
| 3718 | opr ||(self, b:(Any,Any)):String = do (i,j) = b; self || "(" || i || "," j || ")" end |
|---|
| 3719 | opr ||(self, b:(Any,Any,Any)):String = |
|---|
| 3720 | do (i,j,k) = b; self || "(" || i || "," j || "," k || ")" end |
|---|
| 3721 | opr ||(self, b:(Any,Any,Any,Any)):String = |
|---|
| 3722 | do (i,j,k,l) = b; self || "(" || i || "," j || "," k || "," l || ")" end |
|---|
| 3723 | opr ||(self, b:(Any,Any,Any,Any,Any)):String = |
|---|
| 3724 | do (i,j,k,l,m) = b; self || "(" || i || "," j || "," k || "," l || "," m || ")" end |
|---|
| 3725 | opr ||(self, b:(Any,Any,Any,Any,Any,Any)):String = |
|---|
| 3726 | do (i,j,k,l,m,n) = b; self || "(" || i || "," j || "," k || "," l || "," m || "," n || ")" end |
|---|
| 3727 | opr ||(a:Any, self):String = a.toString || self |
|---|
| 3728 | opr ||(self, b:Any):String = self || b.toString |
|---|
| 3729 | |
|---|
| 3730 | (** The operator %|||% with at least one String argument converts to string, |
|---|
| 3731 | then appends with a whitespace separator unless one of the two arguments is |
|---|
| 3732 | empty. If there is an empty argument, the other argument is returned. **) |
|---|
| 3733 | opr |||(self, b:String): String = |
|---|
| 3734 | if |self| = 0 then b |
|---|
| 3735 | elif |b| = 0 then self |
|---|
| 3736 | else self || " " || b |
|---|
| 3737 | end |
|---|
| 3738 | opr |||(self, b:Any): String = self ||| (""||b) |
|---|
| 3739 | opr |||(a:Any, self): String = (""||a) ||| self |
|---|
| 3740 | |
|---|
| 3741 | (** Right now for backward compatibility juxtaposition works like %||% **) |
|---|
| 3742 | opr juxtaposition(a:Any, self):String = (""||a) || self |
|---|
| 3743 | opr juxtaposition(self, b:String):String = self || b |
|---|
| 3744 | opr juxtaposition(self, b:Any):String = self || b |
|---|
| 3745 | |
|---|
| 3746 | (** opr %//% appends with a single newline separator. Note that as |
|---|
| 3747 | with %||% and %|||% at least one argument must be a String. |
|---|
| 3748 | There is a postfix version in FortressLibrary that performs |
|---|
| 3749 | string conversion, but the prefix version must occur before a |
|---|
| 3750 | String. **) |
|---|
| 3751 | opr //(self) : String = "\n"||self |
|---|
| 3752 | opr //(self, a:String): String = self||"\n"||a |
|---|
| 3753 | opr //(self, a:Any): String = self||"\n"||a |
|---|
| 3754 | opr //(a:Any, self): String = a||"\n"||self |
|---|
| 3755 | |
|---|
| 3756 | (** opr %///% appends with a double newline separator. Note that, as |
|---|
| 3757 | with %||% and %|||%, at least one argument must be a String. |
|---|
| 3758 | There is a postfix version in FortressLibrary that performs |
|---|
| 3759 | string conversion, but the prefix version must occur before a |
|---|
| 3760 | String. **) |
|---|
| 3761 | opr ///(self) : String = "\n\n"||self |
|---|
| 3762 | opr ///(self, a:String): String = self||"\n\n"||a |
|---|
| 3763 | opr ///(self, a:Any): String = self||"\n\n"||a |
|---|
| 3764 | opr ///(a:Any, self): String = a||"\n\n"||self |
|---|
| 3765 | |
|---|
| 3766 | end |
|---|
| 3767 | |
|---|
| 3768 | (*********************************************************** |
|---|
| 3769 | * Numeric primitives |
|---|
| 3770 | ************************************************************) |
|---|
| 3771 | |
|---|
| 3772 | nanoTime():ZZ64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$NanoTime") |
|---|
| 3773 | printTaskTrace():() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintTaskTrace") |
|---|
| 3774 | |
|---|
| 3775 | __globalTimeInformation: ZZ64 := 0 |
|---|
| 3776 | recordTime(dummy: Any): () = do __globalTimeInformation := nanoTime() end |
|---|
| 3777 | printTime(dummy: Any): () = do |
|---|
| 3778 | r = nanoTime() |
|---|
| 3779 | e = r - __globalTimeInformation |
|---|
| 3780 | __globalTimeInformation := r |
|---|
| 3781 | secs: ZZ64 = (e+500000) DIV 1000000 |
|---|
| 3782 | println("Operation took " secs "ms") |
|---|
| 3783 | end |
|---|
| 3784 | |
|---|
| 3785 | fromRawBits(a:ZZ64):RR64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$FromRawBits") |
|---|
| 3786 | |
|---|
| 3787 | random(a:Number):RR64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Random") |
|---|
| 3788 | |
|---|
| 3789 | char(a:ZZ32):Char = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Char$Chr") |
|---|
| 3790 | |
|---|
| 3791 | |
|---|
| 3792 | print(a:Any):() = print(a.toString) |
|---|
| 3793 | println(a:Any):() = println(a.toString) |
|---|
| 3794 | (* 0-argument versions handle passing of () to single-argument versions. *) |
|---|
| 3795 | print():() = print("") |
|---|
| 3796 | println():() = println("") |
|---|
| 3797 | print(a: JavaString): () = |
|---|
| 3798 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Print") |
|---|
| 3799 | println(a: JavaString): () = |
|---|
| 3800 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Println") |
|---|
| 3801 | |
|---|
| 3802 | forDigit(x:ZZ32, radix:ZZ32): Maybe[\Char\] = |
|---|
| 3803 | if (radix<2 OR radix>16 OR x<0 OR x>=radix) then |
|---|
| 3804 | Nothing[\Char\] |
|---|
| 3805 | elif (radix <= 12) then |
|---|
| 3806 | forDigit(x, "0123456789xe") |
|---|
| 3807 | else |
|---|
| 3808 | forDigit(x, "0123456789abcdef") |
|---|
| 3809 | end |
|---|
| 3810 | |
|---|
| 3811 | forDigit(x:ZZ32, radixString:String): Maybe[\Char\] = |
|---|
| 3812 | if( 0 <= x < |radixString| ) then |
|---|
| 3813 | Just[\Char\](radixString[x]) |
|---|
| 3814 | else |
|---|
| 3815 | Nothing[\Char\] |
|---|
| 3816 | end |
|---|
| 3817 | |
|---|
| 3818 | |
|---|
| 3819 | (** Convert string to arbitrary integral type. String may contain |
|---|
| 3820 | leading - or +. Valid radixes are 2,8,10,12, and 16. No spaces |
|---|
| 3821 | may occur in the string, and it must have at least one digit. |
|---|
| 3822 | |
|---|
| 3823 | Right now we're oblivious to overflow! This ought to be fixed. |
|---|
| 3824 | |
|---|
| 3825 | This ought to support arbitrary integer types, but right now |
|---|
| 3826 | there's no clean way to convert all the arithmetic to use a |
|---|
| 3827 | provided type without having an instance of that type in hand. |
|---|
| 3828 | Unsigned types in particular are a bit sticky. |
|---|
| 3829 | **) |
|---|
| 3830 | strToInt(s: String, radix: ZZ32): ZZ32 = do |
|---|
| 3831 | (i0, neg) = |
|---|
| 3832 | if s[0] = '-' then (1, true) |
|---|
| 3833 | elif s[0] = '+' then (1, false) |
|---|
| 3834 | else (0,false) end |
|---|
| 3835 | n = |s| - 1 |
|---|
| 3836 | r = SUM[ i <- i0:n] if d <- digit(s[i], radix) then |
|---|
| 3837 | d radix^(n-i) |
|---|
| 3838 | else |
|---|
| 3839 | fail("strToInt(" s.toString "," radix "): non-digit " s[i].toString) |
|---|
| 3840 | end |
|---|
| 3841 | if neg then -r else r end |
|---|
| 3842 | end |
|---|
| 3843 | |
|---|
| 3844 | (** Radix-10 digit conversion. All caveats of the flexible-radix conversion above apply. *) |
|---|
| 3845 | strToInt(s: String): ZZ32 = strToInt(s,10) |
|---|
| 3846 | |
|---|
| 3847 | match(regex:String,some:String):Boolean = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Match") |
|---|
| 3848 | |
|---|
| 3849 | (** postfix %//% appends a single newline separator. The postfix version |
|---|
| 3850 | performs implicit conversion to String, which is why it's a |
|---|
| 3851 | standalone top-level function. Infix and prefix versions are defined by String. **) |
|---|
| 3852 | opr (x:Any)// : String = x||"\n" |
|---|
| 3853 | |
|---|
| 3854 | (** postfix %///% appends a double newline separator. The postfix version |
|---|
| 3855 | performs implicit conversion to String, which is why it's a |
|---|
| 3856 | standalone top-level function. Infix and prefix versions are defined by String. **) |
|---|
| 3857 | opr (x:Any)/// : String = x||"\n\n" |
|---|
| 3858 | |
|---|
| 3859 | (* A way to get environment information from inside of fortress *) |
|---|
| 3860 | getEnvironment(name:String, defaultValue:String):String = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$GetEnvironment") |
|---|
| 3861 | |
|---|
| 3862 | (* These are useful temporary hacks for debugging multi-threaded programs *) |
|---|
| 3863 | printThreadInfo(a:String):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintThreadInfo") |
|---|
| 3864 | printThreadInfo(a:Number):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintThreadInfo") |
|---|
| 3865 | throwError(a:String):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$ThrowError") |
|---|
| 3866 | |
|---|
| 3867 | opr SEQV(a:Any, b:Any):Boolean = |
|---|
| 3868 | builtinPrimitive("com.sun.fortress.interpreter.glue.prim.AnyPrim$SEquiv") |
|---|
| 3869 | |
|---|
| 3870 | opr XOR(a:Boolean, b:Boolean):Boolean = if a then NOT b else b end |
|---|
| 3871 | opr OR(a:Boolean, b:Boolean):Boolean = if a then true else b end |
|---|
| 3872 | opr AND(a:Boolean, b:Boolean):Boolean = if a then b else false end |
|---|
| 3873 | opr OR(a:Boolean, b:()->Boolean):Boolean = if a then true else b() end |
|---|
| 3874 | opr AND(a:Boolean, b:()->Boolean):Boolean = if a then b() else false end |
|---|
| 3875 | opr NOT(a:Boolean):Boolean = if a then false else true end |
|---|
| 3876 | opr ->(a: Boolean, b:Boolean):Boolean = if a then b else true end |
|---|
| 3877 | opr ->(a: Boolean, b:()->Boolean):Boolean = if a then b() else true end |
|---|
| 3878 | opr <->(a: Boolean, b:Boolean):Boolean = a=b |
|---|
| 3879 | |
|---|
| 3880 | true : Boolean = () SEQV () |
|---|
| 3881 | false : Boolean = true SEQV () |
|---|
| 3882 | |
|---|
| 3883 | opr +[\T extends Number\](x:T):T = x |
|---|
| 3884 | |
|---|
| 3885 | (* Shouldn't these operators have to extend something? A,B,C? *) |
|---|
| 3886 | |
|---|
| 3887 | opr =[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do |
|---|
| 3888 | (a1,b1) = t1 |
|---|
| 3889 | (a2,b2) = t2 |
|---|
| 3890 | (a1=a2) AND: (b1=b2) |
|---|
| 3891 | end |
|---|
| 3892 | |
|---|
| 3893 | opr <[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do |
|---|
| 3894 | (a1,b1) = t1 |
|---|
| 3895 | (a2,b2) = t2 |
|---|
| 3896 | typecase _ = a1 CMP a2 of |
|---|
| 3897 | LessThan => true |
|---|
| 3898 | EqualTo => b1 < b2 |
|---|
| 3899 | GreaterThan => false |
|---|
| 3900 | end |
|---|
| 3901 | end |
|---|
| 3902 | |
|---|
| 3903 | opr <=[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do |
|---|
| 3904 | (a1,b1) = t1 |
|---|
| 3905 | (a2,b2) = t2 |
|---|
| 3906 | typecase _ = a1 CMP a2 of |
|---|
| 3907 | LessThan => true |
|---|
| 3908 | EqualTo => b1 <= b2 |
|---|
| 3909 | GreaterThan => false |
|---|
| 3910 | end |
|---|
| 3911 | end |
|---|
| 3912 | |
|---|
| 3913 | opr >[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do |
|---|
| 3914 | (a1,b1) = t1 |
|---|
| 3915 | (a2,b2) = t2 |
|---|
| 3916 | typecase _ = a1 CMP a2 of |
|---|
| 3917 | LessThan => false |
|---|
| 3918 | EqualTo => b1 > b2 |
|---|
| 3919 | GreaterThan => true |
|---|
| 3920 | end |
|---|
| 3921 | end |
|---|
| 3922 | |
|---|
| 3923 | opr >=[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do |
|---|
| 3924 | (a1,b1) = t1 |
|---|
| 3925 | (a2,b2) = t2 |
|---|
| 3926 | typecase _ = a1 CMP a2 of |
|---|
| 3927 | LessThan => false |
|---|
| 3928 | EqualTo => b1 >= b2 |
|---|
| 3929 | GreaterThan => true |
|---|
| 3930 | end |
|---|
| 3931 | end |
|---|
| 3932 | |
|---|
| 3933 | opr CMP[\A,B\](t1:(A,B), t2:(A,B)): Comparison = do |
|---|
| 3934 | (a1,b1) = t1 |
|---|
| 3935 | (a2,b2) = t2 |
|---|
| 3936 | (a1 CMP a2) LEXICO: (b1 CMP b2) |
|---|
| 3937 | end |
|---|
| 3938 | |
|---|
| 3939 | opr =[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do |
|---|
| 3940 | (a1,b1,c1) = t1 |
|---|
| 3941 | (a2,b2,c2) = t2 |
|---|
| 3942 | (a1=a2) AND: (b1=b2) AND: (c1=c2) |
|---|
| 3943 | end |
|---|
| 3944 | |
|---|
| 3945 | opr <[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do |
|---|
| 3946 | (a1,b1,c1) = t1 |
|---|
| 3947 | (a2,b2,c2) = t2 |
|---|
| 3948 | typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of |
|---|
| 3949 | LessThan => true |
|---|
| 3950 | EqualTo => c1 < c2 |
|---|
| 3951 | GreaterThan => false |
|---|
| 3952 | end |
|---|
| 3953 | end |
|---|
| 3954 | |
|---|
| 3955 | opr <=[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do |
|---|
| 3956 | (a1,b1,c1) = t1 |
|---|
| 3957 | (a2,b2,c2) = t2 |
|---|
| 3958 | typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of |
|---|
| 3959 | LessThan => true |
|---|
| 3960 | EqualTo => c1 <= c2 |
|---|
| 3961 | GreaterThan => false |
|---|
| 3962 | end |
|---|
| 3963 | end |
|---|
| 3964 | |
|---|
| 3965 | opr >[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do |
|---|
| 3966 | (a1,b1,c1) = t1 |
|---|
| 3967 | (a2,b2,c2) = t2 |
|---|
| 3968 | typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of |
|---|
| 3969 | LessThan => false |
|---|
| 3970 | EqualTo => c1 > c2 |
|---|
| 3971 | GreaterThan => true |
|---|
| 3972 | end |
|---|
| 3973 | end |
|---|
| 3974 | |
|---|
| 3975 | opr >=[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do |
|---|
| 3976 | (a1,b1,c1) = t1 |
|---|
| 3977 | (a2,b2,c2) = t2 |
|---|
| 3978 | typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of |
|---|
| 3979 | LessThan => false |
|---|
| 3980 | EqualTo => c1 >= c2 |
|---|
| 3981 | GreaterThan => true |
|---|
| 3982 | end |
|---|
| 3983 | end |
|---|
| 3984 | |
|---|
| 3985 | opr CMP[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Comparison = do |
|---|
| 3986 | (a1,b1,c1) = t1 |
|---|
| 3987 | (a2,b2,c2) = t2 |
|---|
| 3988 | (a1 CMP a2) LEXICO: (b1 CMP b2) LEXICO: (c1 CMP c2) |
|---|
| 3989 | end |
|---|
| 3990 | |
|---|
| 3991 | object Box[\T\](var val : T) |
|---|
| 3992 | end |
|---|
| 3993 | |
|---|
| 3994 | end |
|---|