function binaryKernelFunc(name, simpleImpl, complexImpl, dtype) {
    if (complexImpl == null) return ({ inputs, backend })=>{
        const { a, b } = inputs;
        const cpuBackend = backend;
        (0, _cpuUtil.assertNotComplex)([
            a,
            b
        ], name);
        const aVals = cpuBackend.data.get(a.dataId).values;
        const bVals = cpuBackend.data.get(b.dataId).values;
        const decodedAVals = a.dtype === "string" ? // tslint:disable-next-line: no-any
        (0, _tfjsCore.backend_util).fromUint8ToStringArray(aVals) : aVals;
        const decodedBVals = a.dtype === "string" ? // tslint:disable-next-line: no-any
        (0, _tfjsCore.backend_util).fromUint8ToStringArray(bVals) : bVals;
        const $dtype = dtype || a.dtype;
        const [resultData, resultShape] = simpleImpl(a.shape, b.shape, decodedAVals, decodedBVals, $dtype);
        return cpuBackend.makeTensorInfo(resultShape, $dtype, resultData);
    };
    return ({ inputs, backend })=>{
        const { a, b } = inputs;
        const cpuBackend = backend;
        if (a.dtype === "complex64" || b.dtype === "complex64") {
            const $aComplex = (0, _cast.cast)({
                inputs: {
                    x: a
                },
                backend: cpuBackend,
                attrs: {
                    dtype: "complex64"
                }
            });
            const $aComplexVals = cpuBackend.data.get($aComplex.dataId);
            const aReal = $aComplexVals.complexTensorInfos.real;
            const aImag = $aComplexVals.complexTensorInfos.imag;
            const aRealVals = cpuBackend.data.get(aReal.dataId).values;
            const aImagVals = cpuBackend.data.get(aImag.dataId).values;
            const $bComplex = (0, _cast.cast)({
                inputs: {
                    x: b
                },
                backend: cpuBackend,
                attrs: {
                    dtype: "complex64"
                }
            });
            const $bComplexVals = cpuBackend.data.get($bComplex.dataId);
            const bReal = $bComplexVals.complexTensorInfos.real;
            const bImag = $bComplexVals.complexTensorInfos.imag;
            const bRealVals = cpuBackend.data.get(bReal.dataId).values;
            const bImagVals = cpuBackend.data.get(bImag.dataId).values;
            const [resultRealData, resultImagData, resultShape] = complexImpl(a.shape, b.shape, aRealVals, aImagVals, bRealVals, bImagVals);
            const resultReal = cpuBackend.makeTensorInfo(resultShape, "float32", resultRealData);
            const resultImag = cpuBackend.makeTensorInfo(resultShape, "float32", resultImagData);
            const result = (0, _complex.complex)({
                inputs: {
                    real: resultReal,
                    imag: resultImag
                },
                backend: cpuBackend
            });
            cpuBackend.disposeIntermediateTensorInfo($aComplex);
            cpuBackend.disposeIntermediateTensorInfo($bComplex);
            cpuBackend.disposeIntermediateTensorInfo(resultReal);
            cpuBackend.disposeIntermediateTensorInfo(resultImag);
            return result;
        } else {
            const aVals = cpuBackend.data.get(a.dataId).values;
            const bVals = cpuBackend.data.get(b.dataId).values;
            const $dtype = dtype || a.dtype;
            const [resultData, resultShape] = simpleImpl(a.shape, b.shape, aVals, bVals, $dtype);
            return cpuBackend.makeTensorInfo(resultShape, $dtype, resultData);
        }
    };
}
Template that creates the complex type implementation for binary ops.
Supports broadcast.