From 210201dcce89c9d1875056686c57093b5df04a32 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 29 Jan 2015 01:06:30 +0000 Subject: [PATCH] FIx #163 - Array2d.* don't work on non-zero-based arrays --- src/fsharp/FSharp.Core/prim-types.fs | 111 ++++++++++++++++----------- tests/fsharp/core/array/test.fsx | 49 ++++++++++++ 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 899c4fc1573..c83b5fca520 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -833,7 +833,7 @@ namespace Microsoft.FSharp.Core SetArray2D dst i j (GetArray2D src (src1 + i) (src2 + j)) dst - let SetArray2DSub (dst: 'T[,]) src1 src2 len1 len2 src = + let SetArray2DSub (dst: 'T[,]) src1 src2 len1 len2 (src: 'T[,]) = for i = 0 to len1 - 1 do for j = 0 to len2 - 1 do SetArray2D dst (src1+i) (src2+j) (GetArray2D src i j) @@ -858,14 +858,13 @@ namespace Microsoft.FSharp.Core SetArray3D dst i j k (GetArray3D src (src1+i) (src2+j) (src3+k)) dst - let SetArray3DSub (dst: 'T[,,]) src1 src2 src3 len1 len2 len3 src = + let SetArray3DSub (dst: 'T[,,]) src1 src2 src3 len1 len2 len3 (src: 'T[,,]) = for i = 0 to len1 - 1 do for j = 0 to len2 - 1 do for k = 0 to len3 - 1 do SetArray3D dst (src1+i) (src2+j) (src3+k) (GetArray3D src i j k) - let inline GetArray4D (arr: 'T[,,,]) (n1:int) (n2:int) (n3:int) (n4:int) = (# "ldelem.multi 4 !0" type ('T) arr n1 n2 n3 n4 : 'T #) let inline SetArray4D (arr: 'T[,,,]) (n1:int) (n2:int) (n3:int) (n4:int) (x:'T) = (# "stelem.multi 4 !0" type ('T) arr n1 n2 n3 n4 x #) let inline Array4DLength1 (arr: 'T[,,,]) = (# "ldlen.multi 4 0" arr : int #) @@ -888,7 +887,7 @@ namespace Microsoft.FSharp.Core SetArray4D dst i j k m (GetArray4D src (src1+i) (src2+j) (src3+k) (src4+m)) dst - let SetArray4DSub (dst: 'T[,,,]) src1 src2 src3 src4 len1 len2 len3 len4 src = + let SetArray4DSub (dst: 'T[,,,]) src1 src2 src3 src4 len1 len2 len3 len4 (src: 'T[,,,]) = for i = 0 to len1 - 1 do for j = 0 to len2 - 1 do for k = 0 to len3 - 1 do @@ -5359,16 +5358,16 @@ namespace Microsoft.FSharp.Core [] let PowGeneric (one,mul,x:'T,n) = ComputePowerGenericInlined one mul x n - let inline ComputeSlice start finish length = + let inline ComputeSlice bound start finish length = match start, finish with - | None, None -> 0, length - 1 - | None, Some n when n >= 0 -> 0, n - | Some m, None when m <= length -> m, length - 1 + | None, None -> bound, bound + length - 1 + | None, Some n when n >= bound -> bound , n + | Some m, None when m <= bound + length -> m, bound + length - 1 | Some m, Some n -> m, n | _ -> raise (System.IndexOutOfRangeException()) let inline GetArraySlice (arr: _[]) start finish = - let start, finish = ComputeSlice start finish arr.Length + let start, finish = ComputeSlice 0 start finish arr.Length GetArraySub arr start (finish - start + 1) let inline SetArraySlice (dst: _[]) start finish (src:_[]) = @@ -5377,14 +5376,17 @@ namespace Microsoft.FSharp.Core SetArraySub dst start (finish - start + 1) src let GetArraySlice2D (arr: _[,]) start1 finish1 start2 finish2 = - let start1, finish1 = ComputeSlice start1 finish1 (GetArray2DLength1 arr) - let start2, finish2 = ComputeSlice start2 finish2 (GetArray2DLength2 arr) + let bound1 = arr.GetLowerBound(0) + let bound2 = arr.GetLowerBound(1) + let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray2DLength1 arr) + let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray2DLength2 arr) let len1 = (finish1 - start1 + 1) let len2 = (finish2 - start2 + 1) GetArray2DSub arr start1 start2 len1 len2 let inline GetArraySlice2DFixed1 (arr: _[,]) fixed1 start2 finish2 = - let start2, finish2 = ComputeSlice start2 finish2 (GetArray2DLength2 arr) + let bound2 = arr.GetLowerBound(1) + let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray2DLength2 arr) let len2 = (finish2 - start2 + 1) let dst = zeroCreate (if len2 < 0 then 0 else len2) for j = 0 to len2 - 1 do @@ -5392,7 +5394,8 @@ namespace Microsoft.FSharp.Core dst let inline GetArraySlice2DFixed2 (arr: _[,]) start1 finish1 fixed2 = - let start1, finish1 = ComputeSlice start1 finish1 (GetArray2DLength1 arr) + let bound1 = arr.GetLowerBound(0) + let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray2DLength1 arr) let len1 = (finish1 - start1 + 1) let dst = zeroCreate (if len1 < 0 then 0 else len1) for i = 0 to len1 - 1 do @@ -5400,49 +5403,63 @@ namespace Microsoft.FSharp.Core dst let inline SetArraySlice2DFixed1 (dst: _[,]) fixed1 start2 finish2 (src:_[]) = - let start2 = (match start2 with None -> 0 | Some n -> n) - let finish2 = (match finish2 with None -> GetArray2DLength2 dst - 1 | Some n -> n) + let bound2 = dst.GetLowerBound(1) + let start2 = (match start2 with None -> bound2 | Some n -> n) + let finish2 = (match finish2 with None -> bound2 + GetArray2DLength2 dst - 1 | Some n -> n) let len2 = (finish2 - start2 + 1) for j = 0 to len2 - 1 do - SetArray2D dst fixed1 (start2+j) (GetArray src j) + SetArray2D dst fixed1 (bound2+start2+j) (GetArray src j) let inline SetArraySlice2DFixed2 (dst: _[,]) start1 finish1 fixed2 (src:_[]) = - let start1 = (match start1 with None -> 0 | Some n -> n) - let finish1 = (match finish1 with None -> GetArray2DLength1 dst - 1 | Some n -> n) + let bound1 = dst.GetLowerBound(0) + let start1 = (match start1 with None -> bound1 | Some n -> n) + let finish1 = (match finish1 with None -> bound1 + GetArray2DLength1 dst - 1 | Some n -> n) let len1 = (finish1 - start1 + 1) for i = 0 to len1 - 1 do - SetArray2D dst (start1+i) fixed2 (GetArray src i) + SetArray2D dst (bound1+start1+i) fixed2 (GetArray src i) let SetArraySlice2D (dst: _[,]) start1 finish1 start2 finish2 (src:_[,]) = - let start1 = (match start1 with None -> 0 | Some n -> n) - let start2 = (match start2 with None -> 0 | Some n -> n) - let finish1 = (match finish1 with None -> GetArray2DLength1 dst - 1 | Some n -> n) - let finish2 = (match finish2 with None -> GetArray2DLength2 dst - 1 | Some n -> n) + let bound1 = dst.GetLowerBound(0) + let bound2 = dst.GetLowerBound(1) + let start1 = (match start1 with None -> bound1 | Some n -> n) + let start2 = (match start2 with None -> bound2 | Some n -> n) + let finish1 = (match finish1 with None -> bound1 + GetArray2DLength1 dst - 1 | Some n -> n) + let finish2 = (match finish2 with None -> bound2 + GetArray2DLength2 dst - 1 | Some n -> n) SetArray2DSub dst start1 start2 (finish1 - start1 + 1) (finish2 - start2 + 1) src let GetArraySlice3D (arr: _[,,]) start1 finish1 start2 finish2 start3 finish3 = - let start1, finish1 = ComputeSlice start1 finish1 (GetArray3DLength1 arr) - let start2, finish2 = ComputeSlice start2 finish2 (GetArray3DLength2 arr) - let start3, finish3 = ComputeSlice start3 finish3 (GetArray3DLength3 arr) + let bound1 = arr.GetLowerBound(0) + let bound2 = arr.GetLowerBound(1) + let bound3 = arr.GetLowerBound(2) + let start1, finish1 = ComputeSlice bound1 start1 finish1 (GetArray3DLength1 arr) + let start2, finish2 = ComputeSlice bound2 start2 finish2 (GetArray3DLength2 arr) + let start3, finish3 = ComputeSlice bound3 start3 finish3 (GetArray3DLength3 arr) let len1 = (finish1 - start1 + 1) let len2 = (finish2 - start2 + 1) let len3 = (finish3 - start3 + 1) GetArray3DSub arr start1 start2 start3 len1 len2 len3 let SetArraySlice3D (dst: _[,,]) start1 finish1 start2 finish2 start3 finish3 (src:_[,,]) = - let start1 = (match start1 with None -> 0 | Some n -> n) - let start2 = (match start2 with None -> 0 | Some n -> n) - let start3 = (match start3 with None -> 0 | Some n -> n) - let finish1 = (match finish1 with None -> GetArray3DLength1 dst - 1 | Some n -> n) - let finish2 = (match finish2 with None -> GetArray3DLength2 dst - 1 | Some n -> n) - let finish3 = (match finish3 with None -> GetArray3DLength3 dst - 1 | Some n -> n) + let bound1 = dst.GetLowerBound(0) + let bound2 = dst.GetLowerBound(1) + let bound3 = dst.GetLowerBound(2) + let start1 = (match start1 with None -> bound1 | Some n -> n) + let start2 = (match start2 with None -> bound2 | Some n -> n) + let start3 = (match start3 with None -> bound3 | Some n -> n) + let finish1 = (match finish1 with None -> bound1 + GetArray3DLength1 dst - 1 | Some n -> n) + let finish2 = (match finish2 with None -> bound2 + GetArray3DLength2 dst - 1 | Some n -> n) + let finish3 = (match finish3 with None -> bound3 + GetArray3DLength3 dst - 1 | Some n -> n) SetArray3DSub dst start1 start2 start3 (finish1 - start1 + 1) (finish2 - start2 + 1) (finish3 - start3 + 1) src let GetArraySlice4D (arr: _[,,,]) start1 finish1 start2 finish2 start3 finish3 start4 finish4 = - let start1, finish1 = ComputeSlice start1 finish1 (Array4DLength1 arr) - let start2, finish2 = ComputeSlice start2 finish2 (Array4DLength2 arr) - let start3, finish3 = ComputeSlice start3 finish3 (Array4DLength3 arr) - let start4, finish4 = ComputeSlice start4 finish4 (Array4DLength4 arr) + let bound1 = arr.GetLowerBound(0) + let bound2 = arr.GetLowerBound(1) + let bound3 = arr.GetLowerBound(2) + let bound4 = arr.GetLowerBound(3) + let start1, finish1 = ComputeSlice bound1 start1 finish1 (Array4DLength1 arr) + let start2, finish2 = ComputeSlice bound2 start2 finish2 (Array4DLength2 arr) + let start3, finish3 = ComputeSlice bound3 start3 finish3 (Array4DLength3 arr) + let start4, finish4 = ComputeSlice bound4 start4 finish4 (Array4DLength4 arr) let len1 = (finish1 - start1 + 1) let len2 = (finish2 - start2 + 1) let len3 = (finish3 - start3 + 1) @@ -5450,18 +5467,22 @@ namespace Microsoft.FSharp.Core GetArray4DSub arr start1 start2 start3 start4 len1 len2 len3 len4 let SetArraySlice4D (dst: _[,,,]) start1 finish1 start2 finish2 start3 finish3 start4 finish4 (src:_[,,,]) = - let start1 = (match start1 with None -> 0 | Some n -> n) - let start2 = (match start2 with None -> 0 | Some n -> n) - let start3 = (match start3 with None -> 0 | Some n -> n) - let start4 = (match start4 with None -> 0 | Some n -> n) - let finish1 = (match finish1 with None -> Array4DLength1 dst - 1 | Some n -> n) - let finish2 = (match finish2 with None -> Array4DLength2 dst - 1 | Some n -> n) - let finish3 = (match finish3 with None -> Array4DLength3 dst - 1 | Some n -> n) - let finish4 = (match finish4 with None -> Array4DLength4 dst - 1 | Some n -> n) + let bound1 = dst.GetLowerBound(0) + let bound2 = dst.GetLowerBound(1) + let bound3 = dst.GetLowerBound(2) + let bound4 = dst.GetLowerBound(3) + let start1 = (match start1 with None -> bound1 | Some n -> n) + let start2 = (match start2 with None -> bound2 | Some n -> n) + let start3 = (match start3 with None -> bound3 | Some n -> n) + let start4 = (match start4 with None -> bound4 | Some n -> n) + let finish1 = (match finish1 with None -> bound1 + Array4DLength1 dst - 1 | Some n -> n) + let finish2 = (match finish2 with None -> bound2 + Array4DLength2 dst - 1 | Some n -> n) + let finish3 = (match finish3 with None -> bound3 + Array4DLength3 dst - 1 | Some n -> n) + let finish4 = (match finish4 with None -> bound4 + Array4DLength4 dst - 1 | Some n -> n) SetArray4DSub dst start1 start2 start3 start4 (finish1 - start1 + 1) (finish2 - start2 + 1) (finish3 - start3 + 1) (finish4 - start4 + 1) src let inline GetStringSlice (str:string) start finish = - let start, finish = ComputeSlice start finish str.Length + let start, finish = ComputeSlice 0 start finish str.Length let len = finish-start+1 if len <= 0 then String.Empty else str.Substring(start, len) diff --git a/tests/fsharp/core/array/test.fsx b/tests/fsharp/core/array/test.fsx index 34212522242..649e62fc886 100644 --- a/tests/fsharp/core/array/test.fsx +++ b/tests/fsharp/core/array/test.fsx @@ -594,14 +594,63 @@ module Array2Tests = begin //test "a2_sub" // (Array2D.sub a 1 1 2 2 = b) + Array2D.blit b 0 0 a 0 0 2 2 //test "a2_blit" // (Array2D.sub a 0 0 2 2 = b) let _ = test_make_get_set_length () + end +module ArrayNonZeroBasedTestsSlice = + let runTest () = + let arr = (Array2D.initBased 5 4 3 2 (fun i j -> (i,j))) + test "fewoih1" (arr.[6,*] = [|(6, 4); (6, 5)|]) + test "fewoih2" (arr.[*,*].[1,*] = [|(6, 4); (6, 5)|]) + test "fewoih3" (arr.[*,5] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih4" (arr.[*,*].[*,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih5" (arr.GetLowerBound(0) = 5) + test "fewoih6" (arr.GetLowerBound(1) = 4) + test "fewoih7" (arr.[*,*].GetLowerBound(0) = 0) + test "fewoih8" (arr.[*,*].GetLowerBound(1) = 0) + test "fewoih9" (arr.[*,*].[0..,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih10" (arr.[*,*].[1..,1] = [|(6, 5); (7, 5)|]) + let arr2d = + let arr = Array2D.zeroCreateBased 5 4 3 2 + for i in 5..7 do for j in 4..5 do arr.[i,j] <- (i,j) + arr + let arr2d2 = + let arr = Array2D.zeroCreate 3 2 + for i in 0..2 do for j in 0..1 do arr.[i,j] <- (j,i) + arr + test "fewoih11" (arr2d.[6..6,5] = [|(6, 5)|]) + test "fewoih11" (arr2d.[..6,5] = [|(6, 5)|]) + test "fewoih11" (arr2d.[6..,5] = [|(6, 5); (7, 5)|]) + test "fewoih12" (arr2d.[*,*].[1..,1] = [|(6, 5); (7, 5)|]) + arr2d.[*,*] <- arr2d2 + test "fewoih13" (arr2d.[*,*].[0..0,1] = [|(1, 0)|]) + test "fewoih13" (arr2d.[*,*].[1..,1] = [|(1, 1); (1, 2)|]) + test "fewoih13" (arr2d.[*,*].[1,1..] = [|(1, 1)|]) + test "fewoih13" (arr2d.[*,*].[1,0..0] = [|(0, 1)|]) + let arr3d = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |], [|5;4;3|]) :?> (int*int*int)[,,] + for i in 5..7 do for j in 4..5 do for k in 3..3 do arr.[i,j,k] <- (i,j,k) + arr + let arr3d2 = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |]) :?> (int*int*int)[,,] + for i in 0..2 do for j in 0..1 do for k in 0..0 do arr.[i,j,k] <- (k,j,i) + arr + + test "fewoih14" (arr3d.[5,4,3] = (5,4,3)) + test "fewoih15" (arr3d.[*,*,*].[0,0,0] = (5,4,3)) + arr3d.[*,*,*] <- arr3d2 + test "fewoih16" (arr3d.[5,4,3] = (0,0,0)) + test "fewoih16" (arr3d.[5,5,3] = (0,1,0)) + test "fewoih16" (arr3d.[6,5,3] = (0,1,1)) + let _ = runTest() + module Array3Tests = begin let test_make_get_set_length () =