IPv4アドレスのマスクの変換

IPv4アドレスのマスクの変換

1つ目のIPアドレスからビットを数える関数は面白半分で作ったものです。
再帰関数を使う時点でもったいない気が・・・・w
Cなら5行のbitカウントコードにするとCPUのbitカウントより早いらしいです。

namespace Doukakuorg

open System
open System.Text.RegularExpressions

(*
    IPv4アドレスのマスクの変換
    http://ja.doukaku.org/253/flatten/
*)
type C253 public () =
    member this.MaskToBitOld ip =
        if Regex.IsMatch(ip, @"^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$") then
            let masks =
                Map.ofList [
                     1, 0x55555555L;
                     2, 0x33333333L;
                     4, 0x0f0f0f0fL;
                     8, 0x00ff00ffL;
                    16, 0x0000ffffL;
                ]
            let rec bitcount mask bits =
                if 16 < mask then
                    bits
                else
                    bitcount (mask <<< 1) ((bits &&& masks.[mask]) + (bits >>> mask &&& masks.[mask]))
            let bc = bitcount 1
            ip.Split('.')
                |> Array.map (fun a -> bc (Convert.ToInt64(a)))
                |> Array.sum
        else 0L

    member this.MaskToBit ip =
        if Regex.IsMatch(ip, @"^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$") then
            ip.Split('.')
                |> Array.map (fun a -> Convert.ToInt32(a))
                |> Array.map (fun a -> Convert.ToString(a, 2))
                |> Array.fold (fun s n -> s + n) ""
                |> (fun a -> a.Replace("0", "").Length)
        else
            0

    member this.BitToMask bit =
        if 1 <= bit && bit <= 32 then
            (new String('1', bit)).PadRight(32, '0')
                |> (fun a -> [for i in 0..8..(a.Length-1) do yield a.[i .. (i+7)]])
                |> List.map (fun a -> Convert.ToInt32(a, 2))
                |> List.fold (fun s n -> String.Format("{0}.{1}", s, n)) ""
                |> (fun a -> a.[1..])
        else
            "0.0.0.0"