Элегантный способ выровнять матрицу simd_float4x4 - PullRequest
0 голосов
/ 22 мая 2019

Я хотел бы объединить матрицу simd_float4x4 или simd_float3x3 в единый массив элементов с плавающей точкой.

Для обычного массива я бы использовал

let arr = [[1,2,3],[4,5,6],[7,8,9]]
print(arr.flatMap { $0 })

Как можноЯ делаю это для simd_float4x4 или simd_float3x3 структуры элегантно?

Я сейчас использую это,

extension simd_float3x3 {
    var array: [Float] {
        return [columns.0.x, columns.0.y, columns.0.z,
                columns.1.x, columns.1.y, columns.1.z,
                columns.2.x, columns.2.y, columns.2.z]
    }
}

let arr = simd_float3x3.init()
print(arr.array.compactMap({$0}))

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Ну, похоже, что векторы float3 и float4 уже имеют реализацию map (через реализацию протокола Sequence / Collection).

Так что единственное, что нам нужно сделать, это реализовать Collection для матриц:

extension simd_float3x3: Collection {
    public var startIndex: Int {
        return 0
    }

    public var endIndex: Int {
        return 3 // for `sims_float4x4` it would be 4, number of columns
    }

    public func index(after i: Int) -> Int {
        return i + 1
    }
}

и теперь мы можем сделать это:

let matrix: simd_float3x3 = initCodeForTheMatrix()
matrix.flatMap { $0 }

Вы можете объявить этот удобный подпротокол, чтобы не вводить одинаковые startIndex и index(after:) для всех типов матриц:

public protocol SIMDCollection: Collection {}
extension SIMDCollection {
    public var startIndex: Int {
        return 0
    }

    public func index(after i: Int) -> Int {
        return i + 1
    }
}

// And use it like this:
extension simd_float3x3: SIMDCollection {
    public var endIndex: Int {
        return 3
    }
}

extension simd_float4x4: SIMDCollection {
    public var endIndex: Int {
        return 4
    }
}

extension simd_float3x2: SIMDCollection {
    public var endIndex: Int {
        return 3
    }
}

// etc

Это может пойти еще дальше, потому что endIndex будет одинаковым для всех simd_floatX_Y с одинаковыми X и любыми Y. Даже не имеет значения, если это *float* или *double* или что-то еще.

0 голосов
/ 22 мая 2019

Элегант в глазах смотрящего.До сих пор я придумал это:

let s = simd_float3x3(simd_float3(1, 2, 3), simd_float3(4, 5, 6), simd_float3(7, 8, 9)) 

let y = (0..<3).flatMap { x in (0..<3).map { y in s[x][y] } }

print(y)
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
...