gx
chenyc
2025-02-12 ea42ff3ebee1eeb3fb29423aa848a249441db81c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * @license
 * Copyright 2020 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
import { backend_util, Concat, util } from '@tensorflow/tfjs-core';
import { complex } from './Complex';
import { concatImpl } from './Concat_impl';
import { identity } from './Identity';
import { imag } from './Imag';
import { real } from './Real';
import { reshape } from './Reshape';
export function concat(args) {
    const { inputs, backend, attrs } = args;
    const { axis } = attrs;
    const $axis = util.parseAxisParam(axis, inputs[0].shape)[0];
    const shapes = inputs.map(t => t.shape);
    backend_util.assertParamsConsistent(shapes, $axis);
    let outShape = backend_util.computeOutShape(inputs.map(t => t.shape), $axis);
    if (util.sizeFromShape(outShape) === 0) {
        return backend.makeTensorInfo(outShape, inputs[0].dtype, []);
    }
    // Keep only non-empty tensors (ignore tensors with 0 in their shape).
    const $inputs = inputs.filter(t => util.sizeFromShape(t.shape) > 0);
    if ($inputs.length === 1) {
        return identity({ inputs: { x: $inputs[0] }, backend });
    }
    if ($inputs[0].dtype === 'complex64') {
        const reals = $inputs.map((t) => real({ inputs: { input: t }, backend }));
        const imags = $inputs.map((t) => imag({ inputs: { input: t }, backend }));
        const realConcated = concat({ inputs: reals, backend, attrs: { axis: $axis } });
        const imagConcated = concat({ inputs: imags, backend, attrs: { axis: $axis } });
        const result = complex({ inputs: { real: realConcated, imag: imagConcated }, backend });
        reals.forEach(r => backend.disposeIntermediateTensorInfo(r));
        imags.forEach(i => backend.disposeIntermediateTensorInfo(i));
        backend.disposeIntermediateTensorInfo(realConcated);
        backend.disposeIntermediateTensorInfo(imagConcated);
        return result;
    }
    // Any concat of n-dimensional tensors across any axis can be reduced to
    // a concatenation of two-dimensional tensors across the axis 1 by first
    // partitioning the axes of the original tensors into those less than the
    // axis to be concatenated and the rest. Then reshape the tensors
    // into a two-dimensional tensor by collapsing these two sets of axes and
    // concatenate the resulting matrices across the axis 1, finally reshaping
    // the result to have the proper shape.
    const inputs2D = $inputs.map(t => {
        const innerSize = util.sizeFromShape(t.shape.slice($axis));
        const shape = [-1, innerSize];
        return reshape({ inputs: { x: t }, backend, attrs: { shape } });
    });
    const inputsValShapes = inputs2D.map(t => {
        return { vals: backend.data.get(t.dataId).values, shape: t.shape };
    });
    // Concats 2d tensors along axis=1.
    outShape =
        backend_util.computeOutShape(inputs2D.map(t => t.shape), 1 /* axis */);
    const simplyConcat = inputs2D[0].shape[0] === 1;
    const outVals = concatImpl(inputsValShapes, outShape, inputs[0].dtype, simplyConcat);
    const finalOutShape = backend_util.computeOutShape($inputs.map(t => t.shape), $axis);
    const outInfo = backend.makeTensorInfo(finalOutShape, inputs[0].dtype, outVals);
    inputs2D.forEach(t => backend.disposeIntermediateTensorInfo(t));
    return outInfo;
}
export const concatConfig = {
    kernelName: Concat,
    backendName: 'cpu',
    kernelFunc: concat
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29uY2F0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1iYWNrZW5kLWNwdS9zcmMva2VybmVscy9Db25jYXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFDLFlBQVksRUFBRSxNQUFNLEVBQW1FLElBQUksRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBSWxJLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ3BDLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBRWxDLE1BQU0sVUFBVSxNQUFNLENBQ2xCLElBQXlFO0lBRTNFLE1BQU0sRUFBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBQyxHQUFHLElBQUksQ0FBQztJQUN0QyxNQUFNLEVBQUMsSUFBSSxFQUFDLEdBQUcsS0FBSyxDQUFDO0lBRXJCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUU1RCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFbkQsSUFBSSxRQUFRLEdBQUcsWUFBWSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRTdFLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDdEMsT0FBTyxPQUFPLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQzlEO0lBRUQsc0VBQXNFO0lBQ3RFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwRSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3hCLE9BQU8sUUFBUSxDQUFDLEVBQUMsTUFBTSxFQUFFLEVBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBQyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUM7S0FDckQ7SUFFRCxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssV0FBVyxFQUFFO1FBQ3BDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFDLE1BQU0sRUFBRSxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUMsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUMsTUFBTSxFQUFFLEVBQUMsS0FBSyxFQUFFLENBQUMsRUFBQyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUMsQ0FBQztRQUV0RSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsRUFBQyxNQUFNLEVB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QUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRWhFLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQWlCO0lBQ3hDLFVBQVUsRUFBRSxNQUFNO0lBQ2xCLFdBQVcsRUFBRSxLQUFLO0lBQ2xCLFVBQVUsRUFBRSxNQUErQjtDQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQge2JhY2tlbmRfdXRpbCwgQ29uY2F0LCBDb25jYXRBdHRycywgQ29uY2F0SW5wdXRzLCBLZXJuZWxDb25maWcsIEtlcm5lbEZ1bmMsIFRlbnNvckluZm8sIHV0aWx9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZSc7XG5cbmltcG9ydCB7TWF0aEJhY2tlbmRDUFV9IGZyb20gJy4uL2JhY2tlbmRfY3B1JztcblxuaW1wb3J0IHtjb21wbGV4fSBmcm9tICcuL0NvbXBsZXgnO1xuaW1wb3J0IHtjb25jYXRJbXBsfSBmcm9tICcuL0NvbmNhdF9pbXBsJztcbmltcG9ydCB7aWRlbnRpdHl9IGZyb20gJy4vSWRlbnRpdHknO1xuaW1wb3J0IHtpbWFnfSBmcm9tICcuL0ltYWcnO1xuaW1wb3J0IHtyZWFsfSBmcm9tICcuL1JlYWwnO1xuaW1wb3J0IHtyZXNoYXBlfSBmcm9tICcuL1Jlc2hhcGUnO1xuXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0KFxuICAgIGFyZ3M6IHtpbnB1dHM6IENvbmNhdElucHV0cywgYmFja2VuZDogTWF0aEJhY2tlbmRDUFUsIGF0dHJzOiBDb25jYXRBdHRyc30pOlxuICAgIFRlbnNvckluZm8ge1xuICBjb25zdCB7aW5wdXRzLCBiYWNrZW5kLCBhdHRyc30gPSBhcmdzO1xuICBjb25zdCB7YXhpc30gPSBhdHRycztcblxuICBjb25zdCAkYXhpcyA9IHV0aWwucGFyc2VBeGlzUGFyYW0oYXhpcywgaW5wdXRzWzBdLnNoYXBlKVswXTtcblxuICBjb25zdCBzaGFwZXMgPSBpbnB1dHMubWFwKHQgPT4gdC5zaGFwZSk7XG4gIGJhY2tlbmRfdXRpbC5hc3NlcnRQYXJhbXNDb25zaXN0ZW50KHNoYXBlcywgJGF4aXMpO1xuXG4gIGxldCBvdXRTaGFwZSA9IGJhY2tlbmRfdXRpbC5jb21wdXRlT3V0U2hhcGUoaW5wdXRzLm1hcCh0ID0+IHQuc2hhcGUpLCAkYXhpcyk7XG5cbiAgaWYgKHV0aWwuc2l6ZUZyb21TaGFwZShvdXRTaGFwZSkgPT09IDApIHtcbiAgICByZXR1cm4gYmFja2VuZC5tYWtlVGVuc29ySW5mbyhvdXRTaGFwZSwgaW5wdXRzWzBdLmR0eXBlLCBbXSk7XG4gIH1cblxuICAvLyBLZWVwIG9ubHkgbm9uLWVtcHR5IHRlbnNvcnMgKGlnbm9yZSB0ZW5zb3JzIHdpdGggMCBpbiB0aGVpciBzaGFwZSkuXG4gIGNvbnN0ICRpbnB1dHMgPSBpbnB1dHMuZmlsdGVyKHQgPT4gdXRpbC5zaXplRnJvbVNoYXBlKHQuc2hhcGUpID4gMCk7XG4gIGlmICgkaW5wdXRzLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBpZGVudGl0eSh7aW5wdXRzOiB7eDogJGlucHV0c1swXX0sIGJhY2tlbmR9KTtcbiAgfVxuXG4gIGlmICgkaW5wdXRzWzBdLmR0eXBlID09PSAnY29tcGxleDY0Jykge1xuICAgIGNvbnN0IHJlYWxzID0gJGlucHV0cy5tYXAoKHQpID0+IHJlYWwoe2lucHV0czoge2lucHV0OiB0fSwgYmFja2VuZH0pKTtcbiAgICBjb25zdCBpbWFncyA9ICRpbnB1dHMubWFwKCh0KSA9PiBpbWFnKHtpbnB1dHM6IHtpbnB1dDogdH0sIGJhY2tlbmR9KSk7XG5cbiAgICBjb25zdCByZWFsQ29uY2F0ZWQgPSBjb25jYXQoe2lucHV0czogcmVhbHMsIGJhY2tlbmQsIGF0dHJzOiB7YXhpczogJGF4aXN9fSk7XG4gICAgY29uc3QgaW1hZ0NvbmNhdGVkID0gY29uY2F0KHtpbnB1dHM6IGltYWdzLCBiYWNrZW5kLCBhdHRyczoge2F4aXM6ICRheGlzfX0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAgICAgY29tcGxleCh7aW5wdXRzOiB7cmVhbDogcmVhbENvbmNhdGVkLCBpbWFnOiBpbWFnQ29uY2F0ZWR9LCBiYWNrZW5kfSk7XG5cbiAgICByZWFscy5mb3JFYWNoKHIgPT4gYmFja2VuZC5kaXNwb3NlSW50ZXJtZWRpYXRlVGVuc29ySW5mbyhyKSk7XG4gICAgaW1hZ3MuZm9yRWFjaChpID0+IGJhY2tlbmQuZGlzcG9zZUludGVybWVkaWF0ZVRlbnNvckluZm8oaSkpO1xuICAgIGJhY2tlbmQuZGlzcG9zZUludGVybWVkaWF0ZVRlbnNvckluZm8ocmVhbENvbmNhdGVkKTtcbiAgICBiYWNrZW5kLmRpc3Bvc2VJbnRlcm1lZGlhdGVUZW5zb3JJbmZvKGltYWdDb25jYXRlZCk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gQW55IGNvbmNhdCBvZiBuLWRpbWVuc2lvbmFsIHRlbnNvcnMgYWNyb3NzIGFueSBheGlzIGNhbiBiZSByZWR1Y2VkIHRvXG4gIC8vIGEgY29uY2F0ZW5hdGlvbiBvZiB0d28tZGltZW5zaW9uYWwgdGVuc29ycyBhY3Jvc3MgdGhlIGF4aXMgMSBieSBmaXJzdFxuICAvLyBwYXJ0aXRpb25pbmcgdGhlIGF4ZXMgb2YgdGhlIG9yaWdpbmFsIHRlbnNvcnMgaW50byB0aG9zZSBsZXNzIHRoYW4gdGhlXG4gIC8vIGF4aXMgdG8gYmUgY29uY2F0ZW5hdGVkIGFuZCB0aGUgcmVzdC4gVGhlbiByZXNoYXBlIHRoZSB0ZW5zb3JzXG4gIC8vIGludG8gYSB0d28tZGltZW5zaW9uYWwgdGVuc29yIGJ5IGNvbGxhcHNpbmcgdGhlc2UgdHdvIHNldHMgb2YgYXhlcyBhbmRcbiAgLy8gY29uY2F0ZW5hdGUgdGhlIHJlc3VsdGluZyBtYXRyaWNlcyBhY3Jvc3MgdGhlIGF4aXMgMSwgZmluYWxseSByZXNoYXBpbmdcbiAgLy8gdGhlIHJlc3VsdCB0byBoYXZlIHRoZSBwcm9wZXIgc2hhcGUuXG4gIGNvbnN0IGlucHV0czJEID0gJGlucHV0cy5tYXAodCA9PiB7XG4gICAgY29uc3QgaW5uZXJTaXplID0gdXRpbC5zaXplRnJvbVNoYXBlKHQuc2hhcGUuc2xpY2UoJGF4aXMpKTtcbiAgICBjb25zdCBzaGFwZSA9IFstMSwgaW5uZXJTaXplXTtcbiAgICByZXR1cm4gcmVzaGFwZSh7aW5wdXRzOiB7eDogdH0sIGJhY2tlbmQsIGF0dHJzOiB7c2hhcGV9fSk7XG4gIH0pO1xuXG4gIGNvbnN0IGlucHV0c1ZhbFNoYXBlcyA9IGlucHV0czJELm1hcCh0ID0+IHtcbiAgICByZXR1cm4ge3ZhbHM6IGJhY2tlbmQuZGF0YS5nZXQodC5kYXRhSWQpLnZhbHVlcywgc2hhcGU6IHQuc2hhcGV9O1xuICB9KTtcblxuICAvLyBDb25jYXRzIDJkIHRlbnNvcnMgYWxvbmcgYXhpcz0xLlxuICBvdXRTaGFwZSA9XG4gICAgICBiYWNrZW5kX3V0aWwuY29tcHV0ZU91dFNoYXBlKGlucHV0czJELm1hcCh0ID0+IHQuc2hhcGUpLCAxIC8qIGF4aXMgKi8pO1xuICBjb25zdCBzaW1wbHlDb25jYXQgPSBpbnB1dHMyRFswXS5zaGFwZVswXSA9PT0gMTtcbiAgY29uc3Qgb3V0VmFscyA9XG4gICAgICBjb25jYXRJbXBsKGlucHV0c1ZhbFNoYXBlcywgb3V0U2hhcGUsIGlucHV0c1swXS5kdHlwZSwgc2ltcGx5Q29uY2F0KTtcblxuICBjb25zdCBmaW5hbE91dFNoYXBlID1cbiAgICAgIGJhY2tlbmRfdXRpbC5jb21wdXRlT3V0U2hhcGUoJGlucHV0cy5tYXAodCA9PiB0LnNoYXBlKSwgJGF4aXMpO1xuXG4gIGNvbnN0IG91dEluZm8gPVxuICAgICAgYmFja2VuZC5tYWtlVGVuc29ySW5mbyhmaW5hbE91dFNoYXBlLCBpbnB1dHNbMF0uZHR5cGUsIG91dFZhbHMpO1xuXG4gIGlucHV0czJELmZvckVhY2godCA9PiBiYWNrZW5kLmRpc3Bvc2VJbnRlcm1lZGlhdGVUZW5zb3JJbmZvKHQpKTtcblxuICByZXR1cm4gb3V0SW5mbztcbn1cblxuZXhwb3J0IGNvbnN0IGNvbmNhdENvbmZpZzogS2VybmVsQ29uZmlnID0ge1xuICBrZXJuZWxOYW1lOiBDb25jYXQsXG4gIGJhY2tlbmROYW1lOiAnY3B1JyxcbiAga2VybmVsRnVuYzogY29uY2F0IGFzIHVua25vd24gYXMgS2VybmVsRnVuY1xufTtcbiJdfQ==