defmodule Microwaveprop.Weather.Grib2.SimplePacking do @moduledoc false @doc """ Extract a single value from GRIB2 simple-packed data at the given grid index. Formula: value = (R + X * 2^E) * 10^(-D) Where R = reference_value, E = binary_scale, D = decimal_scale, X = raw packed integer at the given index. """ def extract_value(%{bits_per_value: 0} = params, _data, _index) do {:ok, params.reference_value * :math.pow(10, -params.decimal_scale)} end def extract_value(params, data, index) do %{ reference_value: r, binary_scale: e, decimal_scale: d, bits_per_value: n, num_data_points: num } = params if index < 0 or index >= num do {:error, :index_out_of_range} else x = extract_bits(data, index, n) value = (r + x * :math.pow(2, e)) * :math.pow(10, -d) {:ok, value} end end defp extract_bits(data, index, bits_per_value) do bit_offset = index * bits_per_value byte_offset = div(bit_offset, 8) remainder = rem(bit_offset, 8) <<_skip::binary-size(byte_offset), _pad::size(remainder), x::size(bits_per_value)-unsigned-big, _rest::bitstring>> = data x end end