#include "network/switch/routing_alg.h"
#include <cstdint>

namespace dofs {

static inline uint32_t mix32(uint32_t x) noexcept {
        x ^= x >> 16;
        x *= 0x7feb352dU;
        x ^= x >> 15;
        x *= 0x846ca68bU;
        x ^= x >> 16;
        return x;
}

PortId hash_ecmp(NodeId src_node, PortId src_port,
                 NodeId dst_node, PortId dst_port,
                 uint32_t differentiator,
                 uint16_t port_count) noexcept {
        if (port_count == 0) {
                log_error("ERROR", "hash_ecmp ignored: port_count == 0");
                return static_cast<PortId>(0);
        }

        const uint32_t sip = ipv4(src_node, src_port);
        const uint32_t dip = ipv4(dst_node, dst_port);

        uint32_t key = sip;
        key ^= mix32(dip + 0x9e3779b9U);
        key ^= mix32(differentiator + 0x85ebca6bU);

        const uint32_t h = mix32(key);
        const uint16_t idx = static_cast<uint16_t>(h % port_count);
        return static_cast<PortId>(idx);
}

} // namespace dofs
