CastLike#

CastLike - 15#

Version

  • name: CastLike (GitHub)

  • domain: main

  • since_version: 15

  • function: False

  • support_level: SupportType.COMMON

  • shape inference: True

This version of the operator has been available since version 15.

Summary

The operator casts the elements of a given input tensor (the first input) to the same data type as the elements of the second input tensor. See documentation of the Cast operator for further details.

Inputs

  • input (heterogeneous) - T1: Input tensor to be cast.

  • target_type (heterogeneous) - T2: The (first) input tensor will be cast to produce a tensor of the same type as this (second input) tensor.

Outputs

  • output (heterogeneous) - T2: Output tensor produced by casting the first input tensor to have the same type as the second input tensor.

Type Constraints

  • T1 in ( tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) ): Constrain input types. Casting from complex is not supported.

  • T2 in ( tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) ): Constrain output types. Casting to complex is not supported.

Examples

default

shape = (3, 4)
test_cases = [
    ('FLOAT', 'FLOAT16'),
    ('FLOAT', 'DOUBLE'),
    ('FLOAT16', 'FLOAT'),
    ('FLOAT16', 'DOUBLE'),
    ('DOUBLE', 'FLOAT'),
    ('DOUBLE', 'FLOAT16'),
    ('FLOAT', 'STRING'),
    ('STRING', 'FLOAT'),
    ('FLOAT', 'BFLOAT16'),
    ('BFLOAT16', 'FLOAT'),
]

for from_type, to_type in test_cases:
    input_type_proto = None
    output_type_proto = None
    if 'BFLOAT16' == from_type or 'BFLOAT16' == to_type:
        np_fp32 = np.array(['0.47892547', '0.48033667', '0.49968487', '0.81910545',
            '0.47031248', '0.816468', '0.21087195', '0.7229038',
            'NaN', 'INF', '+INF', '-INF'], dtype=np.float32)
        little_endisan = sys.byteorder == 'little'
        np_uint16_view = np_fp32.view(dtype=np.uint16)
        np_bfp16 = np_uint16_view[1::2] if little_endisan else np_uint16_view[0::2]
        if 'BFLOAT16' == to_type:
            assert from_type == 'FLOAT'
            input = np_fp32.reshape([3, 4])
            output = np_bfp16.reshape([3, 4])
            input_type_proto = onnx.helper.make_tensor_type_proto(int(TensorProto.FLOAT), input.shape)
            output_type_proto = onnx.helper.make_tensor_type_proto(int(TensorProto.BFLOAT16), output.shape)
        else:
            assert to_type == 'FLOAT'
            input = np_bfp16.reshape([3, 4])
            #convert bfloat to FLOAT
            np_fp32_zeros = np.zeros((len(np_bfp16) * 2,), dtype=np.uint16)
            if little_endisan:
                np_fp32_zeros[1::2] = np_bfp16
            else:
                np_fp32_zeros[0::2] = np_bfp16
            np_fp32_from_bfloat = np_fp32_zeros.view(dtype=np.float32)
            output = np_fp32_from_bfloat.reshape([3, 4])
            input_type_proto = onnx.helper.make_tensor_type_proto(int(TensorProto.BFLOAT16), input.shape)
            output_type_proto = onnx.helper.make_tensor_type_proto(int(TensorProto.FLOAT), output.shape)
    elif 'STRING' != from_type:
        input = np.random.random_sample(shape).astype(
            TENSOR_TYPE_TO_NP_TYPE[getattr(TensorProto, from_type)])
        if ('STRING' == to_type):
            # Converting input to str, then give it np.object dtype for generating script
            ss = []
            for i in input.flatten():
                s = str(i).encode('utf-8')
                su = s.decode('utf-8')
                ss.append(su)

            output = np.array(ss).astype(np.object).reshape([3, 4])
        else:
            output = input.astype(TENSOR_TYPE_TO_NP_TYPE[getattr(TensorProto, to_type)])
    else:
        input = np.array(['0.47892547', '0.48033667', '0.49968487', '0.81910545',
            '0.47031248', '0.816468', '0.21087195', '0.7229038',
            'NaN', 'INF', '+INF', '-INF'], dtype=np.dtype(np.object)).reshape([3, 4])
        output = input.astype(TENSOR_TYPE_TO_NP_TYPE[getattr(TensorProto, to_type)])
    like = output.flatten()[0:1]
    node = onnx.helper.make_node(
        'CastLike',
        inputs=['input', 'like'],
        outputs=['output'],
    )
    if input_type_proto and output_type_proto:
        expect(node, inputs=[input, like], outputs=[output],
                   name='test_castlike_' + from_type + '_to_' + to_type,
                   input_type_protos=[input_type_proto, output_type_proto],
                   output_type_protos=[output_type_proto])
    else:
        expect(node, inputs=[input, like], outputs=[output],
                   name='test_castlike_' + from_type + '_to_' + to_type)