1 import Base 2 import ../shape/core.bend as Shape 3 import ./layout.bend as Layout 4 import ./core.bend as Core 5 import ./transforms.bend as Transforms 6 import ../storage/main.bend as Storage 7 import ../storage/model.bend as Model 8 import ../storage/refinement.bend as Refinement 9 import ./transform_totality.bend as Totality 10 import ./transpose_spec.bend as Transpose 11 12 law permutation_checked: 13 for +input: Shape.Shape 14 for +axes: List<&2, U32> 15 for plan: Layout.Plan 16 {True{} == Layout.bijective(input, axes) : Bool} 17 18 law permutation_dimensions: 19 for +input: Shape.Shape 20 for +axes: List<&2, U32> 21 for +plan: Layout.Plan 22 {Some{Shape.dimensions(Layout.output(input, axes, plan))} == Layout.reorder(Shape.dimensions(input), axes) : Maybe<&2, List<&2, U32>>} 23 24 law permutation_count: 25 for +input: Shape.Shape 26 for +axes: List<&2, U32> 27 for +plan: Layout.Plan 28 {Shape.logical_numel(Shape.dimensions(input)) == Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))) : Nat} 29 30 law mapped_inverse: 31 for -input: Shape.Shape 32 for -axes: List<&2, U32> 33 for -plan: Layout.Plan 34 for -i: U32 35 for +mapping: Layout.Mapping 36 {Some{Layout.input_words(input, axes, plan, i, mapping)} == 37 Layout.inverse_coordinates(Shape.dimensions(input), axes, Layout.output_words(input, axes, plan, i, mapping), 0) : Maybe<&2, List<&2, U32>>} 38 39 law mapped_flat: 40 for -input: Shape.Shape 41 for -axes: List<&2, U32> 42 for -plan: Layout.Plan 43 for -i: U32 44 for +mapping: Layout.Mapping 45 {Layout.source_index(input, axes, plan, i, mapping) == 46 Layout.flatten_words(Shape.dimensions(input), Layout.input_words(input, axes, plan, i, mapping), 0) : U32} 47 48 law mapped_output: 49 for -input: Shape.Shape 50 for -axes: List<&2, U32> 51 for -plan: Layout.Plan 52 for -i: U32 53 for mapping: Layout.Mapping 54 {Layout.output_words(input, axes, plan, i, mapping) == 55 Layout.reverse_words(Layout.unflatten_words(Layout.reverse_words(Shape.dimensions(Layout.output(input, axes, plan))), i)) : List<&2, U32>} 56 57 law mapped_bounded: 58 for -input: Shape.Shape 59 for -axes: List<&2, U32> 60 for -plan: Layout.Plan 61 for -i: U32 62 for mapping: Layout.Mapping 63 {True{} == U32.is_lt(Layout.source_index(input, axes, plan, i, mapping), Shape.count(input)) : Bool} 64 65 law inverse_coordinate_roundtrip: 66 for -input: Shape.Shape 67 for +axes: List<&2, U32> 68 for -plan: Layout.Plan 69 for -i: U32 70 for +mapping: Layout.Mapping 71 {Layout.reorder(Layout.input_words(input, axes, plan, i, mapping), axes) == 72 Some{Layout.output_words(input, axes, plan, i, mapping)} : Maybe<&2, List<&2, U32>>} 73 74 law reshape_linear_order: 75 for +input: Shape.Shape 76 for +target: Shape.Shape 77 for tensor: Core.Tensor 78 for +index: U32 79 for -same: {Shape.logical_numel(Shape.dimensions(input)) == Shape.logical_numel(Shape.dimensions(target)) : Nat} 80 {Transforms.dynamic_observe(Transforms.reshape_equal(input, target, tensor, same), index) == 81 Core.observe(input, tensor, index) : Maybe<&2, F32>} 82 83 law reshape_target_dimensions: 84 for +input: Shape.Shape 85 for +target: Shape.Shape 86 for tensor: Core.Tensor 87 for -same: {Shape.logical_numel(Shape.dimensions(input)) == Shape.logical_numel(Shape.dimensions(target)) : Nat} 88 {Transforms.dynamic_dimensions(Transforms.reshape_equal(input, target, tensor, same)) == Shape.dimensions(target) : List<&2, U32>} 89 90 law copy_input_preservation: 91 for +depth: Nat 92 for array: Array 93 for +index: U32 94 for +other: U32 95 for balanced: Model.Balanced(F32, depth, array) 96 {Model.observe(F32, depth, Refinement.first(F32, Array.get(F32, array, index)), Refinement.route(depth, other)) == 97 Model.observe(F32, depth, array, Refinement.route(depth, other)) : Maybe<&2, F32>} 98 99 law copy_write_frame: 100 for +depth: Nat 101 for array: Array 102 for +index: U32 103 for +other: U32 104 for +value: F32 105 for balanced: Model.Balanced(F32, depth, array) 106 {Model.observe(F32, depth, Array.set(F32, array, index, value), Refinement.route(depth, other)) == 107 Model.select(F32, Model.same(depth, Refinement.route(depth, index), Refinement.route(depth, other)), value, 108 Model.observe(F32, depth, array, Refinement.route(depth, other))) : Maybe<&2, F32>} 109 110 law zero_count_skips_copy: 111 for +input: Shape.Shape 112 for +axes: List<&2, U32> 113 for +plan: Layout.Plan 114 for source: Core.Tensor 115 for target: Core.Tensor 116 for +cursor: Nat 117 for empty: {Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))) == 0n : Nat} 118 {Transforms.copy_loop(Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))), input, axes, plan, source, target, cursor) == 119 (source, Done{target}) : Core.Tensor & Result<&2, &1, Transforms.Error, Core.Tensor>} 120 121 law natural_cursor_checked: 122 for -input: Shape.Shape 123 for -axes: List<&2, U32> 124 for -plan: Layout.Plan 125 for -cursor: Nat 126 for result: Transforms.NaturalCopy 127 Transforms.CursorValid(input, axes, plan, cursor, result) 128 129 law copy_source_mapping: 130 for -input: Shape.Shape 131 for -axes: List<&2, U32> 132 for -plan: Layout.Plan 133 for -output_index: U32 134 for -mapping: Layout.Mapping 135 for -source: Core.Tensor 136 for certificate: Core.Read 137 {Core.read_value(input, Core.read_flat(input, source, Layout.source_index(input, axes, plan, output_index, mapping))) == 138 Core.certificate_value(input, source, Layout.source_index(input, axes, plan, output_index, mapping), certificate) : Maybe<&2, F32>} 139 140 law primitive_source_mapping: 141 for -input: Shape.Shape 142 for -axes: List<&2, U32> 143 for -plan: Layout.Plan 144 for -output_index: U32 145 for +mapping: Layout.Mapping 146 for +depth: Nat 147 for array: Array 148 for balanced: Model.Balanced(F32, depth, array) 149 {Some{Refinement.second(F32, Array.get(F32, array, Layout.source_index(input, axes, plan, output_index, mapping)))} == 150 Model.observe(F32, depth, array, Refinement.route(depth, Layout.source_index(input, axes, plan, output_index, mapping))) : Maybe<&2, F32>} 151 152 law copy_value_mapping: 153 for -input: Shape.Shape 154 for -axes: List<&2, U32> 155 for +plan: Layout.Plan 156 for +depth: Nat 157 for +length: Nat 158 for array: Array 159 for +index: U32 160 for source: Core.Tensor 161 for +value: F32 162 for balanced: Model.Balanced(F32, depth, array) 163 for -valid: {Storage.bounds(depth, length) == True{} : Bool} 164 for -exact: {length == Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))) : Nat} 165 for allowed: {Nat.is_lt(U32.to_nat(index), length) == True{} : Bool} 166 for matched: {Storage.index_matches(depth, length, index) == True{} : Bool} 167 {Transforms.copy_observe(input, axes, plan, 168 Transforms.copy_read(input, axes, plan, index, source => target => (source, Done{target}), 169 Core.TTensor{Storage.Owned{depth, length, array, balanced, valid}, exact}, (source, Done{value})), index) == Some{value} : Maybe<&2, F32>} 170 171 law checked_copy_step_mapping: 172 for +input: Shape.Shape 173 for +axes: List<&2, U32> 174 for +plan: Layout.Plan 175 for +index: U32 176 for +mapping: Layout.Mapping 177 for map_exact: {Done{mapping} == Layout.map_index(input, axes, plan, index) : Result<&2, &2, Layout.Error, Layout.Mapping>} 178 for -source: Core.Tensor 179 for certificate: Core.Read 180 for +depth: Nat 181 for +length: Nat 182 for array: Array 183 for balanced: Model.Balanced(F32, depth, array) 184 for -valid: {Storage.bounds(depth, length) == True{} : Bool} 185 for -exact: {length == Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))) : Nat} 186 for allowed: {Nat.is_lt(U32.to_nat(index), length) == True{} : Bool} 187 for matched: {Storage.index_matches(depth, length, index) == True{} : Bool} 188 {Transforms.copy_observe(input, axes, plan, 189 Transforms.copy_step(input, axes, plan, source, 190 Core.TTensor{Storage.Owned{depth, length, array, balanced, valid}, exact}, index), index) == 191 Core.certificate_value(input, source, Layout.source_index(input, axes, plan, index, mapping), certificate) : Maybe<&2, F32>} 192 193 law checked_copy_source_meaning: 194 for +input: Shape.Shape 195 for +axes: List<&2, U32> 196 for +plan: Layout.Plan 197 for +index: U32 198 for +mapping: Layout.Mapping 199 for map_exact: {Done{mapping} == Layout.map_index(input, axes, plan, index) : Result<&2, &2, Layout.Error, Layout.Mapping>} 200 for source: Core.Tensor 201 for +depth: Nat 202 for +length: Nat 203 for array: Array 204 for balanced: Model.Balanced(F32, depth, array) 205 for -valid: {Storage.bounds(depth, length) == True{} : Bool} 206 for -exact: {length == Shape.logical_numel(Shape.dimensions(Layout.output(input, axes, plan))) : Nat} 207 for allowed: {Nat.is_lt(U32.to_nat(index), length) == True{} : Bool} 208 for matched: {Storage.index_matches(depth, length, index) == True{} : Bool} 209 Transforms.CopyMeaning 211 212 law initial_prefix: 213 for -input: Shape.Shape 214 for -axes: List<&2, U32> 215 for -plan: Layout.Plan 216 for -source: Core.Tensor 217 for -target: Core.Tensor 218 Transforms.Prefix 219 220 law advance_prefix: 221 for -input: Shape.Shape 222 for -axes: List<&2, U32> 223 for -plan: Layout.Plan 224 for -original: Core.Tensor 225 for -before_source: Core.Tensor 226 for -after_source: Core.Tensor 227 for -before_target: Core.Tensor 228 for -after_target: Core.Tensor 229 for -cursor: Nat 230 for prefix: Transforms.Prefix 231 for advanced: Transforms.Advanced 232 Transforms.Prefix 233 234 law whole_copy_interpretation: 235 for +input: Shape.Shape 236 for +axes: List<&2, U32> 237 for +plan: Layout.Plan 238 for source: Core.Tensor 239 for target: Core.Tensor 240 Transforms.WholeCopyModel 241 242 law permute_result_interpretation: 243 for +input: Shape.Shape 244 for source: Core.Tensor 245 for +axes: List<&2, U32> 246 Transforms.PublicModel 247 248 law transpose_result_interpretation: 249 for +input: Shape.Shape 250 for source: Core.Tensor 251 for +a: U32 252 for +b: U32 253 Transforms.PublicModel 255 256 law reshape_result_interpretation: 257 for +input: Shape.Shape 258 for source: Core.Tensor 259 for +dimensions: List<&2, U32> 260 Transforms.ReshapeModel 261 262 law reshape_inverse_observations: 263 for +input: Shape.Shape 264 for source: Core.Tensor 265 for +dimensions: List<&2, U32> 266 Transforms.ReshapeInverseModel 267 268 law mapping_reference: 269 for +input: Shape.Shape 270 for +axes: List<&2, U32> 271 for +plan: Layout.Plan 272 for +index: U32 273 for mapping: Layout.Mapping 274 {Some{Layout.source_index(input, axes, plan, index, mapping)} == Layout.reference_source(input, axes, plan, index) : Maybe<&2, U32>} 275 276 law mapped_mathematical_bounded: 277 for +input: Shape.Shape 278 for +axes: List<&2, U32> 279 for +plan: Layout.Plan 280 for +index: U32 281 for mapping: Layout.Mapping 282 {Nat.is_lt(U32.to_nat(Layout.source_index(input, axes, plan, index, mapping)), 283 Shape.logical_numel(Shape.dimensions(input))) == True{} : Bool} 284 285 law natural_word_exact: 286 for +number: Nat 287 for +limit: U32 288 for +within: {Nat.is_le(number, U32.to_nat(limit)) == True{} : Bool} 289 {U32.to_nat(U32.from_nat(number)) == number : Nat} 290 291 law codec_flatten_decode: 292 for +shape: Shape.Shape 293 for +index: U32 294 for +inside: {True{} == Nat.is_lt(U32.to_nat(index), Shape.elements(shape)) : Bool} 295 {Layout.flatten_words(Shape.dimensions(shape), 296 Layout.reverse_words(Layout.unflatten_words(Layout.reverse_words(Shape.dimensions(shape)), index)), 0) == index : U32} 297 298 law reshape_valid_success: 299 for +input: Shape.Shape 300 for +target: Shape.Shape 301 for source: Core.Tensor 302 for -same: {Shape.logical_numel(Shape.dimensions(input)) == Shape.logical_numel(Shape.dimensions(target)) : Nat} 303 Transforms.ReshapeSuccessModel 304 305 law reshape_inverse_valid_success: 306 for +input: Shape.Shape 307 for +target: Shape.Shape 308 for source: Core.Tensor 309 for -same: {Shape.logical_numel(Shape.dimensions(input)) == Shape.logical_numel(Shape.dimensions(target)) : Nat} 310 Transforms.ReshapeInverseSuccessModel 311 312 law permutation_valid_success: 313 for +input: Shape.Shape 314 for +axes: List<&2, U32> 315 for +valid: {True{} == Layout.bijective(input, axes) : Bool} 316 Totality.PlanSuccess 317 318 law tensor_read_valid_success: 319 for +shape: Shape.Shape 320 for source: Core.Tensor 321 for +index: U32 322 for -inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(shape))) == True{} : Bool} 323 Totality.ReadSuccess 324 325 law tensor_write_valid_success: 326 for +shape: Shape.Shape 327 for target: Core.Tensor 328 for +index: U32 329 for +value: F32 330 for -inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(shape))) == True{} : Bool} 331 Totality.WriteSuccess 332 333 law decoded_words_valid_success: 334 for +shape: Shape.Shape 335 for +index: U32 336 for +inside: {True{} == Nat.is_lt(U32.to_nat(index), Shape.elements(shape)) : Bool} 337 Totality.WordsSuccess 339 340 law permute_axes_length_rejection: 341 for +input: Shape.Shape 342 for source: Core.Tensor 343 for +axes: List<&2, U32> 344 for -wrong: {False{} == Nat.is_eq(Shape.rank_dimensions(axes), Shape.rank_dimensions(Shape.dimensions(input))) : Bool} 345 Totality.PermuteFailure 346 347 law permute_axis_bounds_rejection: 348 for +input: Shape.Shape 349 for source: Core.Tensor 350 for +axes: List<&2, U32> 351 for -ranked: {True{} == Nat.is_eq(Shape.rank_dimensions(axes), Shape.rank_dimensions(Shape.dimensions(input))) : Bool} 352 for -outside: {False{} == Layout.bounded(axes, Shape.rank(input)) : Bool} 353 Totality.PermuteFailure 354 355 law permute_duplicate_axes_rejection: 356 for +input: Shape.Shape 357 for source: Core.Tensor 358 for +axes: List<&2, U32> 359 for -ranked: {True{} == Nat.is_eq(Shape.rank_dimensions(axes), Shape.rank_dimensions(Shape.dimensions(input))) : Bool} 360 for -bounded: {True{} == Layout.bounded(axes, Shape.rank(input)) : Bool} 361 for -duplicate: {False{} == Layout.unique(axes) : Bool} 362 Totality.PermuteFailure 363 364 law transpose_axis_bounds_rejection: 365 for +input: Shape.Shape 366 for source: Core.Tensor 367 for +a: U32 368 for +b: U32 369 for -outside: {False{} == Transpose.valid(input, a, b) : Bool} 370 Totality.TransposeFailure 371 372 law reshape_element_count_rejection: 373 for +input: Shape.Shape 374 for +target: Shape.Shape 375 for source: Core.Tensor 376 for -different: {False{} == Nat.is_eq(Shape.logical_numel(Shape.dimensions(input)), Shape.logical_numel(Shape.dimensions(target))) : Bool} 377 Totality.ReshapeFailure 378 379 law mapping_index_rejection: 380 for +input: Shape.Shape 381 for +axes: List<&2, U32> 382 for +plan: Layout.Plan 383 for +index: U32 384 for +outside: {False{} == U32.is_lt(index, Shape.count(Layout.output(input, axes, plan))) : Bool} 385 {Layout.map_index(input, axes, plan, index) == Fail{Layout.ShapeError{Shape.FlatIndexOutOfBounds{}}} : 386 Result<&2, &2, Layout.Error, Layout.Mapping>} 387 388 law codec_decode_flatten: 389 for +shape: Shape.Shape 390 for +values: List<&2, U32> 391 for +valid: Layout.WordsValid(Shape.dimensions(shape), values) 392 {Layout.reverse_words(Layout.unflatten_words(Layout.reverse_words(Shape.dimensions(shape)), 393 Layout.flatten_words(Shape.dimensions(shape), values, 0))) == values : List<&2, U32>} 394 395 law mapping_valid_success: 396 for +input: Shape.Shape 397 for +axes: List<&2, U32> 398 for +plan: Layout.Plan 399 for +index: U32 400 for +inside: {True{} == U32.is_lt(index, Shape.count(Layout.output(input, axes, plan))) : Bool} 401 Totality.MappingSuccess 402 403 law natural_cursor_exact_conversion: 404 for +shape: Shape.Shape 405 for +cursor: Nat 406 for +within: {Nat.is_le(cursor, Shape.elements(shape)) == True{} : Bool} 407 Transforms.CursorExact 408 409 law copy_step_valid_success: 410 for +input: Shape.Shape 411 for +axes: List<&2, U32> 412 for +plan: Layout.Plan 413 for source: Core.Tensor 414 for target: Core.Tensor 415 for +index: U32 416 for +inside: {True{} == U32.is_lt(index, Shape.count(Layout.output(input, axes, plan))) : Bool} 417 Totality.CopyStepSuccess 418 419 law natural_step_valid_success: 420 for +input: Shape.Shape 421 for +axes: List<&2, U32> 422 for +plan: Layout.Plan 423 for +cursor: Nat 424 for source: Core.Tensor 425 for target: Core.Tensor 426 for +inside: {True{} == Nat.is_lt(cursor, Shape.elements(Layout.output(input, axes, plan))) : Bool} 427 Totality.NaturalSuccess 428 429 law copy_loop_valid_success: 430 for +fuel: Nat 431 for +input: Shape.Shape 432 for +axes: List<&2, U32> 433 for +plan: Layout.Plan 434 for +cursor: Nat 435 for source: Core.Tensor 436 for target: Core.Tensor 437 for +within: {Nat.is_le(Nat.add(fuel, cursor), Shape.elements(Layout.output(input, axes, plan))) == True{} : Bool} 438 Totality.CopySuccess 439 440 law permute_valid_success: 441 for +input: Shape.Shape 442 for source: Core.Tensor 443 for +axes: List<&2, U32> 444 for +valid: {True{} == Layout.bijective(input, axes) : Bool} 445 Totality.PublicSuccess 446 447 law inverse_axes_valid: 448 for +input: Shape.Shape 449 for +axes: List<&2, U32> 450 for +plan: Layout.Plan 451 {True{} == Layout.bijective(Layout.output(input, axes, plan), Totality.inverse_axes(input, axes)) : Bool} 452 453 law inverse_permutation_dimensions: 454 for +input: Shape.Shape 455 for +axes: List<&2, U32> 456 for +plan: Layout.Plan 457 for +inverse: Layout.Plan 458 {Shape.dimensions(Layout.output(Layout.output(input, axes, plan), Totality.inverse_axes(input, axes), inverse)) == Shape.dimensions(input) : List<&2, U32>} 459 460 law inverse_mapping_restores_index: 461 for +input: Shape.Shape 462 for +axes: List<&2, U32> 463 for +plan: Layout.Plan 464 for +inverse: Layout.Plan 465 for +index: U32 466 for +second: Layout.Mapping 467 for +first: Layout.Mapping 469 {Layout.source_index(input, axes, plan, 470 Layout.source_index(Layout.output(input, axes, plan), Totality.inverse_axes(input, axes), inverse, index, second), first) == index : U32} 471 472 law permute_typed_success: 473 for +input: Shape.Shape 474 for source: Core.Tensor 475 for +axes: List<&2, U32> 476 for +valid: {True{} == Layout.bijective(input, axes) : Bool} 477 Totality.TypedPermutation 478 479 law permute_inverse_restoration: 480 for +input: Shape.Shape 481 for source: Core.Tensor 482 for +axes: List<&2, U32> 483 for +valid: {True{} == Layout.bijective(input, axes) : Bool} 484 Totality.PermutationInverse 485 486 law transpose_valid_success: 487 for +input: Shape.Shape 488 for source: Core.Tensor 489 for +a: U32 490 for +b: U32 491 for +inside: {True{} == Transpose.valid(input, a, b) : Bool} 492 Totality.PublicSuccess 493 494 law transpose_requested_result: 495 for +input: Shape.Shape 496 for source: Core.Tensor 497 for +a: U32 498 for +b: U32 499 for +inside: {True{} == Transpose.valid(input, a, b) : Bool} 500 Totality.RequestedTranspose 501 502 law transpose_inverse_restoration: 503 for +input: Shape.Shape 504 for source: Core.Tensor 505 for +a: U32 506 for +b: U32 507 for +inside: {True{} == Transpose.valid(input, a, b) : Bool} 508 Totality.TransposeInverse