1

I found this C# code for CRC16 but I need it on F# :

using System;

public class Crc16 {
    const ushort polynomial = 0xA001;
    ushort[] table = new ushort[256];

    public ushort ComputeChecksum(byte[] bytes) {
        ushort crc = 0;
        for(int i = 0; i < bytes.Length; ++i) {
            byte index = (byte)(crc ^ bytes[i]);
            crc = (ushort)((crc >> 8) ^ table[index]);
        }
        return crc;
    }

    public byte[] ComputeChecksumBytes(byte[] bytes) {
        ushort crc = ComputeChecksum(bytes);
        return BitConverter.GetBytes(crc);
    }

    public Crc16() {
        ushort value;
        ushort temp;
        for(ushort i = 0; i < table.Length; ++i) {
            value = 0;
            temp = i;
            for(byte j = 0; j < 8; ++j) {
                if(((value ^ temp) & 0x0001) != 0) {
                    value = (ushort)((value >> 1) ^ polynomial);
                }else {
                    value >>= 1;
                }
                temp >>= 1;
            }
            table[i] = value;
        }
    }
}

Here is where I started :

let ComputeChecksum(bytes : byte array) =
    let mutable crc = 0us
    for i = 0 to bytes.Length do
        let index = (crc ^^^ bytes.[i]) // ? uint16 and byte

So I think C# version is taking here first or second byte. So I want to know how C# '^' will work here ? And how can I translate this line of C# code to F# ?

cnd
  • 32,616
  • 62
  • 183
  • 313

2 Answers2

3

This computes the same result as your C# code.

type Crc16() =
  let polynomial = 0xA001us
  let table = Array.init 256 (fun i ->
    ((0us, uint16 i), [0y..7y]) 
    ||> Seq.fold (fun (value, temp) j ->
      let newValue = 
        match (value ^^^ temp) &&& 0x0001us with
        | 0us -> value >>> 1
        | _ -> ((value >>> 1) ^^^ polynomial)
      newValue, temp >>> 1)
    |> fst)
  member __.ComputeChecksum(bytes:byte[]) =
    (0us, bytes) ||> Seq.fold (fun crc byt ->
      let index = byte (crc ^^^ (uint16 byt))
      (crc >>> 8) ^^^ table.[int index])
Daniel
  • 47,404
  • 11
  • 101
  • 179
1

C# ^ and F# ^^^ are both the XOR operator. They should work the same. Is that what you're asking?

Gabe
  • 84,912
  • 12
  • 139
  • 238
  • It's actually the casting operator `(byte)` that is "taking" the first byte. You just want to do a similar cast in F#: `index = byte (crc ^^^ bytes.[i])` – Gabe Sep 12 '11 at 06:30
  • This expression was expected to have type uint16 but here has type byte – cnd Sep 12 '11 at 06:39
  • note in F#, the literal for a byte is `uy` not `us` - this is what is causing the problem with the XOR - and explains the compiler error – John Palmer Sep 12 '11 at 07:12
  • In C# example (ushort crc = 0;) crc is 2 bytes (16bits) (After all I want to get crc16, not crc8) and there is no error, so ^ and ^^^ works different and I want to know how ^ works to make the same action on F#. – cnd Sep 12 '11 at 07:17
  • Oh, I see. Maybe you need `index = (byte crc) ^^^ bytes.[i]`. – Gabe Sep 12 '11 at 11:24