print("""// types are encoded as ubf where:
//  u = 0: signed, u = 1: unsigned
//  b = 0: 32-bit, b = 1: 64-bit
//  f = 0: int,    f = 1: float/double
//  unsigned float/double is interpreted as bool
// width is ww where:
//  ww = 00: 1 component
//  ww = 01: 2 components
//  ww = 10: 3 components
//  ww = 11: 4 components
// full conversion code is wwsssddd where:
//  ww = width
//  sss = src type
//  ddd = dst type
// case values are in octal
""")
types = [
    "int",
    "float",
    "long",
    "double",
    "uint",
    "int",      # 32-bit bool
    "ulong",
    "long",     # 64-bit bool
]
#does not include size (2 or 4, 3 is special)
vec_types = [
    "ivec",
    "vec",
    "lvec",
    "dvec",
    "uivec",
    "ivec",     # 32-bit bool
    "ulvec",
    "lvec",     # 64-bit bool
]
convert_matrix = [
    #i  f  l  d   ui b  ul B
    [0, 1, 1, 1,  0, 3, 1, 3],  # i
    [1, 0, 1, 1,  1, 3, 1, 3],  # f
    [1, 1, 0, 1,  1, 3, 0, 3],  # l
    [1, 1, 1, 0,  1, 3, 1, 3],  # d

    [0, 1, 1, 1,  0, 3, 1, 3],  # ui
    [2, 2, 2, 2,  2, 0, 2, 3],  # 32-bit bool
    [1, 1, 0, 1,  1, 3, 0, 3],  # ul
    [2, 2, 2, 2,  2, 3, 2, 0],  # 64-bit bool
]

def case_str(width, src_type, dst_type):
    case = (width << 6) | (src_type << 3) | (dst_type)
    return f"case {case:04o}:"

#FIXME look into using gcc's __builtin_convertvector
def cast_str(width, src_type, dst_type):
    if width & 1:
        return f"(pr_{vec_types[dst_type]}{width+1}_t)"
    else:
        return f"(pr_{types[dst_type]}_t)"

def src_str(width, src_type, dst_type):
    if width & 1:
        return f"OPA({vec_types[src_type]}{width+1})"
    else:
        return f"OPA({types[src_type]})"

def dst_str(width, src_type, dst_type):
    if width & 1:
        return f"OPC({vec_types[dst_type]}{width+1})"
    else:
        return f"OPC({types[dst_type]})"

def zero_str(width, src_type):
    zeros = "{%s}" % (", ".join(["0"] * (width + 1)))
    return f"{cast_str(width, src_type, src_type)} {zeros}"

def one_str(width, src_type):
    ones = "{%s}" % (", ".join(["1"] * (width + 1)))
    return f"{cast_str(width, src_type, src_type)} {ones}"

def expand_str(width, src, pref=""):
    src = [f"{pref}{src}[{i}]" for i in range(width + 1)]
    return "{%s}" % (", ".join(src));

for width in range(4):
    for src_type in range(8):
        for dst_type in range(8):
            case = case_str(width, src_type, dst_type)
            cast = cast_str(width, src_type, dst_type)
            src = src_str(width, src_type, dst_type)
            dst = dst_str(width, src_type, dst_type)
            mode = convert_matrix[src_type][dst_type]
            if mode == 0:
                if dst_type & 2 != src_type & 2:
                    continue
                if dst_type & 2:
                    src = src_str(width, 2, 2)
                    dst = dst_str(width, 2, 2)
                else:
                    src = src_str(width, 0, 0)
                    dst = dst_str(width, 0, 0)
                if width == 2:
                    print(f"{case} VectorCopy(&{src},&{dst}); break;")
                else:
                    print(f"{case} {dst} = {src}; break;")
            elif mode == 1:
                if width == 0:
                    print(f"{case} {dst} = {cast} {src}; break;")
                elif width == 2:
                    print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;")
                else:
                    expand = expand_str(width, src, f"(pr_{types[dst_type]}_t)")
                    print(f"{case} {dst} = {cast} {expand}; break;")
            elif mode == 2:
                one = one_str(width, src_type)
                if width == 0:
                    print(f"{case} {dst} = !!{src}; break;")
                elif width == 2:
                    print(f"{case} VectorCompUop(&{dst},!!,&{src}); break;")
                else:
                    expand = expand_str(width, src, "!!")
                    print(f"{case} {dst} = {cast} {expand}; break;")
            elif mode == 3:
                zero = zero_str(width, src_type)
                if width == 0:
                    print(f"{case} {dst} = -!!{src}; break;")
                elif width == 2:
                    print(f"{case} VectorCompUop(&{dst},-!!,&{src}); break;")
                else:
                    expand = expand_str(width, src, "-!!")
                    print(f"{case} {dst} = {cast} {expand}; break;")
