/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 3-Clause Clear License
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
 * License was not distributed with this source code in the LICENSE file, you
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
 * Alliance for Open Media Patent License 1.0 was not distributed with this
 * source code in the PATENTS file, you can obtain it at
 * aomedia.org/license/patent-license/.
 */

// This tool is a gadget for offline probability training.
// A binary executable avm_entropy_optimizer will be generated in tools/. It
// parses a binary file consisting of counts written in the format of
// FRAME_COUNTS in entropymode.h, and computes optimized probability tables
// and CDF tables, which will be written to a new c file optimized_probs.c
// according to format in the codebase.
//
// Command line: ./avm_entropy_optimizer [directory of the count file]
//
// The input file can either be generated by encoding a single clip by
// turning on entropy_stats experiment, or be collected at a larger scale at
// which a python script which will be provided soon can be used to aggregate
// multiple stats output.

#include <assert.h>
#include <stdio.h>

#include "av2/common/enums.h"
#include "av2/common/quant_common.h"
#include "config/avm_config.h"

#include "av2/encoder/encoder.h"

#define STRING_MAX 2048  // should be large but limited to copy CDF name
#define SPACES_PER_TAB 2
#define CDF_MAX_SIZE 16

typedef unsigned int avm_count_type;
// A log file recording parsed counts
static FILE *logfile;  // TODO(yuec): make it a command line option

static void counts_to_cdf(const avm_count_type *counts, avm_cdf_prob *cdf,
                          int modes) {
  int64_t csum[CDF_MAX_SIZE];
  assert(modes <= CDF_MAX_SIZE);

  csum[0] = counts[0] + 1;
  for (int i = 1; i < modes; ++i) csum[i] = counts[i] + 1 + csum[i - 1];

  for (int i = 0; i < modes; ++i) fprintf(logfile, "%d ", counts[i]);
  fprintf(logfile, "\n");

  int64_t sum = csum[modes - 1];
  const int64_t round_shift = sum >> 1;
  for (int i = 0; i < modes; ++i) {
    cdf[i] = (csum[i] * CDF_PROB_TOP + round_shift) / sum;
    cdf[i] = AVMMIN(cdf[i], CDF_PROB_TOP - (modes - 1 + i) * 4);
    cdf[i] = (i == 0) ? AVMMAX(cdf[i], 4) : AVMMAX(cdf[i], cdf[i - 1] + 4);
  }
}

static int parse_counts_for_cdf_opt(avm_count_type **ct_ptr,
                                    FILE *const probsfile, int tabs,
                                    int dim_of_cts, int *cts_each_dim) {
  if (dim_of_cts < 1) {
    fprintf(stderr, "The dimension of a counts vector should be at least 1!\n");
    return 1;
  }
  const int total_modes = cts_each_dim[0];
  if (dim_of_cts == 1) {
    assert(total_modes <= CDF_MAX_SIZE);
    avm_cdf_prob cdfs[CDF_MAX_SIZE];
    avm_count_type *counts1d = *ct_ptr;

    counts_to_cdf(counts1d, cdfs, total_modes);
    (*ct_ptr) += total_modes;

    if (tabs > 0) fprintf(probsfile, "%*c", tabs * SPACES_PER_TAB, ' ');
    fprintf(probsfile, "AVM_CDF%d(", total_modes);
    for (int k = 0; k < total_modes - 1; ++k) {
      fprintf(probsfile, "%d", cdfs[k]);
      if (k < total_modes - 2) fprintf(probsfile, ", ");
    }
    fprintf(probsfile, ")");
  } else {
    for (int k = 0; k < total_modes; ++k) {
      int tabs_next_level;

      if (dim_of_cts == 2)
        fprintf(probsfile, "%*c{ ", tabs * SPACES_PER_TAB, ' ');
      else
        fprintf(probsfile, "%*c{\n", tabs * SPACES_PER_TAB, ' ');
      tabs_next_level = dim_of_cts == 2 ? 0 : tabs + 1;

      if (parse_counts_for_cdf_opt(ct_ptr, probsfile, tabs_next_level,
                                   dim_of_cts - 1, cts_each_dim + 1)) {
        return 1;
      }

      if (dim_of_cts == 2) {
        if (k == total_modes - 1)
          fprintf(probsfile, " }\n");
        else
          fprintf(probsfile, " },\n");
      } else {
        if (k == total_modes - 1)
          fprintf(probsfile, "%*c}\n", tabs * SPACES_PER_TAB, ' ');
        else
          fprintf(probsfile, "%*c},\n", tabs * SPACES_PER_TAB, ' ');
      }
    }
  }
  return 0;
}

// helper function to estimate RAM/ROM memory for CDfs/sytax entries
// only called when --memory is given as an input to the program
static void count_memory(int *cts_each_dim, int dim_of_cts, char *prefix,
                         int has_rom_multiplier, int *total_count, int *dim_arr,
                         int minus_entries, char *cdf_category) {
  int mfactor = 15;   // number of bits used per context per symbol - 1
  int moffset = 5;    // bits offset for RAM
  int tot_count = 1;  // total bit counts per syntax
  int ctx_count = 0;  // total context count per syntax
  int para_bits = 9;  // additional ROM bits needed by PARA

  if (dim_arr == NULL) {
    int dim_last = cts_each_dim[dim_of_cts - 1];
    for (int i = 0; i < dim_of_cts - 1; i++) {
      tot_count *= cts_each_dim[i];
    }
    tot_count -= minus_entries;
    ctx_count = tot_count;
    tot_count = tot_count * ((dim_last - 1) * mfactor + moffset);
  } else {
    int total_entries = 0;
    if (dim_of_cts == 4) {
      ctx_count += cts_each_dim[0] * cts_each_dim[1] * cts_each_dim[2];
      for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
        for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
          for (int d2_idx = 0; d2_idx < cts_each_dim[2]; ++d2_idx) {
            int num_of_modes = dim_arr[d0_idx];
            if (num_of_modes > 0) {
              total_entries += ((num_of_modes - 1) * mfactor + moffset);
            }
          }
        }
      }
      tot_count = total_entries;
    } else if (dim_of_cts == 3) {
      ctx_count += cts_each_dim[0] * cts_each_dim[1];
      for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
        for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
          int num_of_modes = dim_arr[d0_idx];
          if (num_of_modes > 0) {
            total_entries += ((num_of_modes - 1) * mfactor + moffset);
          }
        }
      }
      tot_count = total_entries;
    }
  }

  char string[STRING_MAX];
  strcpy(string, prefix);
  char *subs = strstr(string, "_prob ") + 6;
  char *token = strtok(subs, "[");

  if (subs != NULL) {
    printf("%-48.48s ", token);
    if (!has_rom_multiplier) {
      printf("RAM %6d bits %-8.2f bytes %-5.2f kbytes ", tot_count,
             ((float)tot_count) / 8.0, ((float)tot_count) / 8.0 / 1024.0);
      int rom_count = tot_count + ctx_count * para_bits;
      printf("ROM %6d bits %-8.2f bytes %-5.2f kbytes ", rom_count,
             ((float)rom_count) / 8.0, ((float)rom_count) / 8.0 / 1024.0);
      *total_count += tot_count;
    } else {
      printf("RAM %6d bits %-8.2f bytes %-5.2f kbytes ", tot_count / 4,
             ((float)tot_count) / 8.0 / 4.0,
             ((float)tot_count) / 8.0 / 1024.0 / 4);

      int rom_count = tot_count + ctx_count * para_bits;
      printf("ROM %6d bits %-8.2f bytes %-5.2f kbytes ", rom_count,
             ((float)rom_count) / 8.0, ((float)rom_count) / 8.0 / 1024.0);
      *total_count += tot_count / 4;
      ctx_count /= 4;
    }
    printf(" CTXs %-4.1d %-4.12s \n", ctx_count, cdf_category);
  }
}

/* Optimize CDF entries with CDF memory counter
 * counts             : Pointer to relevent syntax counts from
 * probsfile          : Pointer to probability output
 * dim_of_cts         : Dimension of the CDF table including
 * prefix             : Prefix for CDF name as defined in the standard
 * has_rom_multiplier : Whether the ROM counts need to be multiplied with
 *                      TOKEN_Q_CDFS
 * total_cnt          : Variable to keep track of total bits across all syntax
 * minus_entries      : Some CDF tables have unused context entries that need
 *                      to be subtracted simply count the unused contexts
 *                      (excluding the symbol counts)
 * mem_wanted         : Whether to optimize CDF entries or run in
 *                      memory computation mode instead
 * cdf_category       : Input char array to assign CDF to a category
 */
static void optimize_cdf_table(avm_count_type *counts, FILE *const probsfile,
                               int dim_of_cts, int *cts_each_dim, char *prefix,
                               int has_rom_multiplier, int *total_cnt,
                               int minus_entries, bool mem_wanted,
                               char *cdf_category) {
  if (mem_wanted) {
    count_memory(cts_each_dim, dim_of_cts, prefix, has_rom_multiplier,
                 total_cnt, NULL, minus_entries, cdf_category);
    return;
  }

  avm_count_type *ct_ptr = counts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);
  if (parse_counts_for_cdf_opt(&ct_ptr, probsfile, 1, dim_of_cts,
                               cts_each_dim)) {
    fprintf(probsfile, "Optimizer failed!\n");
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

/* See optimize_cdf_table for usage.
   modes_each_ctx: input symbol counts per each context row
*/
static void optimize_cdf_table_var_modes_2d(avm_count_type *counts,
                                            FILE *const probsfile,
                                            int dim_of_cts, int *cts_each_dim,
                                            int *modes_each_ctx, char *prefix,
                                            int has_rom_multiplier,
                                            int *total_cnt, bool mem_wanted,
                                            char *cdf_category) {
  avm_count_type *ct_ptr = counts;
  if (mem_wanted) {
    count_memory(cts_each_dim, dim_of_cts, prefix, has_rom_multiplier,
                 total_cnt, modes_each_ctx, 0, cdf_category);
    return;
  }
  assert(dim_of_cts == 2);
  (void)dim_of_cts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);

  for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
    int num_of_modes = modes_each_ctx[d0_idx];

    if (num_of_modes > 0) {
      fprintf(probsfile, "%*c{ ", SPACES_PER_TAB, ' ');
      parse_counts_for_cdf_opt(&ct_ptr, probsfile, 0, 1, &num_of_modes);
      ct_ptr += cts_each_dim[1] - num_of_modes;
      fprintf(probsfile, " },\n");
    } else {
      fprintf(probsfile, "%*c{ 0 },\n", SPACES_PER_TAB, ' ');
      fprintf(logfile, "dummy cdf, no need to optimize\n");
      ct_ptr += cts_each_dim[1];
    }
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

/* See optimize_cdf_table for usage.
   modes_each_ctx: input symbol counts per each context row
*/
static void optimize_cdf_table_var_modes_3d(avm_count_type *counts,
                                            FILE *const probsfile,
                                            int dim_of_cts, int *cts_each_dim,
                                            int *modes_each_ctx, char *prefix,
                                            int has_rom_multiplier,
                                            int *total_cnt, bool mem_wanted,
                                            char *cdf_category) {
  if (mem_wanted) {
    count_memory(cts_each_dim, dim_of_cts, prefix, has_rom_multiplier,
                 total_cnt, modes_each_ctx, 0, cdf_category);
    return;
  }
  avm_count_type *ct_ptr = counts;

  assert(dim_of_cts == 3);
  (void)dim_of_cts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);

  for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
    fprintf(probsfile, "%*c{\n", SPACES_PER_TAB, ' ');
    for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
      int num_of_modes = modes_each_ctx[d0_idx];

      if (num_of_modes > 0) {
        fprintf(probsfile, "%*c{ ", 2 * SPACES_PER_TAB, ' ');
        parse_counts_for_cdf_opt(&ct_ptr, probsfile, 0, 1, &num_of_modes);
        ct_ptr += cts_each_dim[2] - num_of_modes;
        fprintf(probsfile, " },\n");
      } else {
        fprintf(probsfile, "%*c{ 0 },\n", 2 * SPACES_PER_TAB, ' ');
        fprintf(logfile, "dummy cdf, no need to optimize\n");
        ct_ptr += cts_each_dim[2];
      }
    }
    fprintf(probsfile, "%*c},\n", SPACES_PER_TAB, ' ');
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

/* See optimize_cdf_table for usage.
   modes_each_ctx: input symbol counts per each context row
*/
static void optimize_cdf_table_var_modes_4d(avm_count_type *counts,
                                            FILE *const probsfile,
                                            int dim_of_cts, int *cts_each_dim,
                                            int *modes_each_ctx, char *prefix,
                                            int has_rom_multiplier,
                                            int *total_cnt, bool mem_wanted,
                                            char *cdf_category) {
  if (mem_wanted) {
    count_memory(cts_each_dim, dim_of_cts, prefix, has_rom_multiplier,
                 total_cnt, modes_each_ctx, 0, cdf_category);
    return;
  }
  avm_count_type *ct_ptr = counts;

  assert(dim_of_cts == 4);
  (void)dim_of_cts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);

  for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
    fprintf(probsfile, "%*c{\n", SPACES_PER_TAB, ' ');
    for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
      fprintf(probsfile, "%*c{\n", 2 * SPACES_PER_TAB, ' ');
      for (int d2_idx = 0; d2_idx < cts_each_dim[2]; ++d2_idx) {
        int num_of_modes = modes_each_ctx[d0_idx];

        if (num_of_modes > 0) {
          fprintf(probsfile, "%*c{ ", 3 * SPACES_PER_TAB, ' ');
          parse_counts_for_cdf_opt(&ct_ptr, probsfile, 0, 1, &num_of_modes);
          ct_ptr += cts_each_dim[3] - num_of_modes;
          fprintf(probsfile, " },\n");
        } else {
          fprintf(probsfile, "%*c{ 0 },\n", 3 * SPACES_PER_TAB, ' ');
          fprintf(logfile, "dummy cdf, no need to optimize\n");
          ct_ptr += cts_each_dim[3];
        }
      }
      fprintf(probsfile, "%*c},\n", 2 * SPACES_PER_TAB, ' ');
    }
    fprintf(probsfile, "%*c},\n", SPACES_PER_TAB, ' ');
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

// Like optimize_cdf_table_var_modes_3d, but the number of modes varies across
// the context dimension.
static void optimize_cdf_table_var_modes_3d_inner(
    avm_count_type *counts, FILE *const probsfile, int dim_of_cts,
    int *cts_each_dim, int *modes_each_ctx, char *prefix) {
  avm_count_type *ct_ptr = counts;

  assert(dim_of_cts == 3);
  (void)dim_of_cts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);

  for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
    fprintf(probsfile, "%*c{\n", SPACES_PER_TAB, ' ');
    for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
      int num_of_modes = modes_each_ctx[d1_idx];

      if (num_of_modes > 0) {
        fprintf(probsfile, "%*c{ ", 2 * SPACES_PER_TAB, ' ');
        parse_counts_for_cdf_opt(&ct_ptr, probsfile, 0, 1, &num_of_modes);
        ct_ptr += cts_each_dim[2] - num_of_modes;
        fprintf(probsfile, " },\n");
      } else {
        fprintf(probsfile, "%*c{ 0 },\n", 2 * SPACES_PER_TAB, ' ');
        fprintf(logfile, "dummy cdf, no need to optimize\n");
        ct_ptr += cts_each_dim[2];
      }
    }
    fprintf(probsfile, "%*c},\n", SPACES_PER_TAB, ' ');
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

// Like optimize_cdf_table_var_modes_4d, but the number of modes varies across
// the last dimension.
static void optimize_cdf_table_var_modes_4d_inner(
    avm_count_type *counts, FILE *const probsfile, int dim_of_cts,
    int *cts_each_dim, int *modes_each_ctx, char *prefix) {
  avm_count_type *ct_ptr = counts;

  assert(dim_of_cts == 4);
  (void)dim_of_cts;

  fprintf(probsfile, "%s = {\n", prefix);
  fprintf(logfile, "%s\n", prefix);

  for (int d0_idx = 0; d0_idx < cts_each_dim[0]; ++d0_idx) {
    fprintf(probsfile, "%*c{\n", SPACES_PER_TAB, ' ');
    for (int d1_idx = 0; d1_idx < cts_each_dim[1]; ++d1_idx) {
      fprintf(probsfile, "%*c{\n", 2 * SPACES_PER_TAB, ' ');
      for (int d2_idx = 0; d2_idx < cts_each_dim[2]; ++d2_idx) {
        int num_of_modes = modes_each_ctx[d2_idx];

        if (num_of_modes > 0) {
          fprintf(probsfile, "%*c{ ", 3 * SPACES_PER_TAB, ' ');
          parse_counts_for_cdf_opt(&ct_ptr, probsfile, 0, 1, &num_of_modes);
          ct_ptr += cts_each_dim[3] - num_of_modes;
          fprintf(probsfile, " },\n");
        } else {
          fprintf(probsfile, "%*c{ 0 },\n", 3 * SPACES_PER_TAB, ' ');
          fprintf(logfile, "dummy cdf, no need to optimize\n");
          ct_ptr += cts_each_dim[3];
        }
      }
      fprintf(probsfile, "%*c},\n", 2 * SPACES_PER_TAB, ' ');
    }
    fprintf(probsfile, "%*c},\n", SPACES_PER_TAB, ' ');
  }
  fprintf(probsfile, "};\n\n");
  fprintf(logfile, "============================\n");
}

int main(int argc, const char **argv) {
  if (argc < 2) {
    fprintf(stderr, "Please specify the input stats file! or type --memory\n");
    exit(EXIT_FAILURE);
  }

  FRAME_COUNTS fc;
  FILE *statsfile;
  FILE *probsfile;

  const bool mem_wanted = !strcmp("--memory", argv[1]);

  if (mem_wanted) {
    printf("Computing Syntax/CDF Memory, probability won't be optimized. \n");
    statsfile = NULL;
    probsfile = NULL;
  } else {
    statsfile = fopen(argv[1], "rb");
    if (statsfile == NULL) {
      fprintf(stderr, "Failed to open input stat file!\n");
      exit(EXIT_FAILURE);
    } else {
      const size_t bytes = fread(&fc, sizeof(FRAME_COUNTS), 1, statsfile);
      if (!bytes) {
        fclose(statsfile);
        return 1;
      }
    }
    probsfile = fopen("optimized_probs.c", "w");
    if (probsfile == NULL) {
      fprintf(stderr,
              "Failed to create output file for optimized entropy tables!\n");
      exit(EXIT_FAILURE);
    }
    logfile = fopen("avm_entropy_optimizer_parsed_counts.log", "w");
    if (logfile == NULL) {
      fprintf(stderr, "Failed to create log file for parsed counts!\n");
      exit(EXIT_FAILURE);
    }
  }

  int cts_each_dim[10];
  int total_count = 0;
  cts_each_dim[0] = INTRA_MODE_SETS;
  optimize_cdf_table(&fc.y_mode_set_idx[0], probsfile, 1, cts_each_dim,
                     "const avm_cdf_prob "
                     "default_y_mode_set_cdf[CDF_SIZE(INTRA_MODE_SETS)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  cts_each_dim[0] = Y_MODE_CONTEXTS;
  cts_each_dim[1] = LUMA_INTRA_MODE_INDEX_COUNT;
  optimize_cdf_table(&fc.y_mode_idx[0][0], probsfile, 2, cts_each_dim,
                     "const avm_cdf_prob "
                     "default_y_mode_idx_cdf[Y_MODE_CONTEXTS][CDF_SIZE(LUMA_"
                     "INTRA_MODE_INDEX_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  cts_each_dim[1] = LUMA_INTRA_MODE_OFFSET_COUNT;
  optimize_cdf_table(
      &fc.y_mode_idx_offset[0][0], probsfile, 2, cts_each_dim,
      "const avm_cdf_prob "
      "default_y_mode_idx_offset_cdf[Y_MODE_CONTEXTS][CDF_SIZE(LUMA_"
      "INTRA_MODE_OFFSET)]",
      0, &total_count, 0, mem_wanted, "Intra");

  /* Intra mode (chroma) */
  cts_each_dim[0] = UV_MODE_CONTEXTS;
  cts_each_dim[1] = CHROMA_INTRA_MODE_INDEX_COUNT;
  optimize_cdf_table(&fc.uv_mode[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_uv_mode_cdf[UV_MODE_CONTEXTS]"
                     "[CDF_SIZE(CHROMA_INTRA_MODE_INDEX_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  cts_each_dim[0] = CFL_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.cfl_mode[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_cfl_cdf[CFL_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* MRL index */
  cts_each_dim[0] = MRL_INDEX_CONTEXTS;
  cts_each_dim[1] = MRL_LINE_NUMBER;
  optimize_cdf_table(&fc.mrl_index[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_mrl_index_cdf"
                     "[MRL_INDEX_CONTEXTS][CDF_SIZE(MRL_LINE_NUMBER)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* MRL index */
  cts_each_dim[0] = MRL_INDEX_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.multi_line_mrl[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_multi_line_mrl_cdf"
                     "[MRL_INDEX_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* cctx type */
  cts_each_dim[0] = CCTX_TYPES;
  optimize_cdf_table(
      &fc.cctx_type[0], probsfile, 1, cts_each_dim,
      "static const avm_cdf_prob default_cctx_type_cdf[CDF_SIZE(CCTX_TYPES)]",
      0, &total_count, 0, mem_wanted, "Transforms");

  cts_each_dim[0] = INTER_SDP_BSIZE_GROUP;
  cts_each_dim[1] = REGION_TYPES;
  optimize_cdf_table(&fc.region_type[0][0], probsfile, 2, cts_each_dim,
                     "static avm_cdf_prob default_region_type_cdf"
                     "[INTER_SDP_BSIZE_GROUP][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Partitions");

  cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
  cts_each_dim[1] = PARTITION_CONTEXTS;
  cts_each_dim[2] = 2;
  // Account for unused partition contexts.
  int do_split_reduce = 40;
  do_split_reduce += 60;
  optimize_cdf_table(
      &fc.do_split[0][0][0], probsfile, 3, cts_each_dim,
      "static avm_cdf_prob default_do_split_cdf"
      "[PARTITION_STRUCTURE_NUM][PARTITION_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, do_split_reduce, mem_wanted,
      "Partitions");  // minus unused context entries
  cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
  cts_each_dim[1] = SQUARE_SPLIT_CONTEXTS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(
      &fc.do_square_split[0][0][0], probsfile, 3, cts_each_dim,
      "static avm_cdf_prob default_do_square_split_cdf"
      "[PARTITION_STRUCTURE_NUM][SQUARE_SPLIT_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Partitions");

  cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
  cts_each_dim[1] = PARTITION_CONTEXTS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(
      &fc.rect_type[0][0][0], probsfile, 3, cts_each_dim,
      "static avm_cdf_prob default_rect_type_cdf"
      "[PARTITION_STRUCTURE_NUM][PARTITION_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 96, mem_wanted,
      "Partitions");  // minus unused context entries

  cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
  cts_each_dim[1] = NUM_RECT_CONTEXTS;
  cts_each_dim[2] = PARTITION_CONTEXTS;
  cts_each_dim[3] = 2;
  int do_ext_partition_reduce = 264;
  do_ext_partition_reduce += 64;
  optimize_cdf_table(&fc.do_ext_partition[0][0][0][0], probsfile, 4,
                     cts_each_dim,
                     "static avm_cdf_prob default_do_ext_partition_cdf"
                     "[PARTITION_STRUCTURE_NUM][NUM_RECT_CONTEXTS][PARTITION_"
                     "CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, do_ext_partition_reduce, mem_wanted,
                     "Partitions");  // minus unused context entries
  cts_each_dim[0] = PARTITION_STRUCTURE_NUM;
  cts_each_dim[1] = NUM_RECT_CONTEXTS;
  cts_each_dim[2] = PARTITION_CONTEXTS;
  cts_each_dim[3] = 2;
  int do_uneven_4way_partition_reduce = 320;
  do_uneven_4way_partition_reduce += 24;
  optimize_cdf_table(
      &fc.do_uneven_4way_partition[0][0][0][0], probsfile, 4, cts_each_dim,
      "static avm_cdf_prob default_do_uneven_4way_partition_cdf"
      "[PARTITION_STRUCTURE_NUM][NUM_RECT_CONTEXTS][PARTITION_CONTEXTS][CDF_"
      "SIZE(2)]",
      0, &total_count, do_uneven_4way_partition_reduce, mem_wanted,
      "Partitions");  // minus unused context entries

  cts_each_dim[0] = DELTA_Q_PROBS + 1;
  optimize_cdf_table(&fc.delta_q_cnts[0], probsfile, 1, cts_each_dim,
                     "static avm_cdf_prob default_delta_q_cdf"
                     "[CDF_SIZE(DELTA_Q_PROBS + 1)]",
                     0, &total_count, 0, mem_wanted, "Other");

  cts_each_dim[0] = 2;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = STX_TYPES;
  optimize_cdf_table(&fc.stx_cnts[0][0][0], probsfile, 3, cts_each_dim,
                     "static avm_cdf_prob default_stx_cdf"
                     "[2][TX_SIZES][CDF_SIZE(STX_TYPES)]",
                     0, &total_count, 0, mem_wanted, "Transforms");

#if CONFIG_IST_ANY_SET
  cts_each_dim[0] = IST_SET_SIZE;
  optimize_cdf_table(&fc.stx_set_cnts[0], probsfile, 1, cts_each_dim,
                     "static avm_cdf_prob default_most_probable_stx_set_cdf"
                     "[CDF_SIZE(IST_SET_SIZE)]",
                     0, &total_count, 0, mem_wanted, "Transforms");
#endif  // CONFIG_IST_ANY_SET

  cts_each_dim[0] = NUM_MV_PREC_MPP_CONTEXT;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.pb_mv_mpp_flag_cnts[0][0], probsfile, 2, cts_each_dim,
      "static avm_cdf_prob default_pb_mv_most_probable_precision_cdf"
      "[NUM_MV_PREC_MPP_CONTEXT][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = MV_PREC_DOWN_CONTEXTS;
  cts_each_dim[1] = NUM_PB_FLEX_QUALIFIED_MAX_PREC;
  cts_each_dim[2] = FLEX_MV_COSTS_SIZE;
  optimize_cdf_table(&fc.pb_mv_precision_cnts[0][0][0], probsfile, 3,
                     cts_each_dim,
                     "static avm_cdf_prob default_pb_mv_precision_cdf"
                     "[MV_PREC_DOWN_CONTEXTS][NUM_PB_FLEX_QUALIFIED_MAX_PREC]"
                     "[CDF_SIZE(FLEX_MV_COSTS_SIZE)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  // MVD/blockvector coding related CDFs
  for (int ibc = 0; ibc < 2; ibc++) {
    nmv_context_count *nmvc_cnts = (ibc == 0) ? &fc.nmvc_cnts : &fc.ndvc_cnts;
    cts_each_dim[0] = 2;
    optimize_cdf_table(&nmvc_cnts->joint_shell_set_cnts[0], probsfile, 1,
                       cts_each_dim,
                       "static avm_cdf_prob joint_shell_set_cdf_placeholder"
                       "[CDF_SIZE(2)]",
                       0, &total_count, 0, mem_wanted, "Inter");
    cts_each_dim[0] = NUM_MV_PRECISIONS;
    cts_each_dim[1] = FIRST_SHELL_CLASS;
    optimize_cdf_table(&nmvc_cnts->joint_shell_class_0_cnts[0][0], probsfile, 2,
                       cts_each_dim,
                       "static avm_cdf_prob joint_shell_class_0_cdf_placeholder"
                       "[NUM_MV_PRECISIONS][CDF_SIZE(FIRST_SHELL_CLASS)]",
                       0, &total_count, 0, mem_wanted, "Inter");
    cts_each_dim[0] = NUM_MV_PRECISIONS;
    cts_each_dim[1] = SECOND_SHELL_CLASS;
    optimize_cdf_table(&nmvc_cnts->joint_shell_class_1_cnts[0][0], probsfile, 2,
                       cts_each_dim,
                       "static avm_cdf_prob joint_shell_class_1_cdf_placeholder"
                       "[NUM_MV_PRECISIONS][CDF_SIZE(SECOND_SHELL_CLASS)]",
                       0, &total_count, 0, mem_wanted, "Inter");

    cts_each_dim[0] = 2;
    optimize_cdf_table(
        &nmvc_cnts->joint_shell_last_two_classes_cnts[0], probsfile, 1,
        cts_each_dim,
        "static avm_cdf_prob joint_shell_last_two_classes_cdf_placeholder"
        "[CDF_SIZE(2)]",
        0, &total_count, 0, mem_wanted, "Inter");

    cts_each_dim[0] = 2;
    cts_each_dim[1] = 2;
    optimize_cdf_table(
        &nmvc_cnts->shell_offset_low_class_cnts[0][0], probsfile, 2,
        cts_each_dim,
        "static avm_cdf_prob shell_offset_low_class_cdf_placeholder"
        "[2][CDF_SIZE(2)]",
        0, &total_count, 0, mem_wanted, "Inter");

    cts_each_dim[0] = 3;
    cts_each_dim[1] = 2;
    optimize_cdf_table(&nmvc_cnts->shell_offset_class2_cnts[0][0], probsfile, 2,
                       cts_each_dim,
                       "static avm_cdf_prob shell_offset_class2_cdf_placeholder"
                       "[3][CDF_SIZE(2)]",
                       0, &total_count, 0, mem_wanted, "Inter");

    cts_each_dim[0] = NUM_CTX_CLASS_OFFSETS;
    cts_each_dim[1] = SHELL_INT_OFFSET_BIT;
    cts_each_dim[2] = 2;
    optimize_cdf_table(
        &nmvc_cnts->shell_offset_other_class_cnts[0][0][0], probsfile, 3,
        cts_each_dim,
        "static avm_cdf_prob shell_offset_other_class_cdf_placeholder"
        "[NUM_CTX_CLASS_OFFSETS][SHELL_INT_OFFSET_BIT][CDF_SIZE(2)]",
        0, &total_count, 0, mem_wanted, "Inter");
    cts_each_dim[0] = NUM_CTX_COL_MV_GTX;
    cts_each_dim[1] = 2;
    optimize_cdf_table(
        &nmvc_cnts->col_mv_greater_flags_cnts[0][0], probsfile, 2, cts_each_dim,
        "static avm_cdf_prob col_mv_greater_flags_cdf_placeholder"
        "[NUM_CTX_COL_MV_GTX][CDF_SIZE(2)]",
        0, &total_count, 0, mem_wanted, "Inter");

    cts_each_dim[0] = NUM_CTX_COL_MV_INDEX;
    cts_each_dim[1] = 2;
    optimize_cdf_table(&nmvc_cnts->col_mv_index_cnts[0][0], probsfile, 2,
                       cts_each_dim,
                       "static avm_cdf_prob col_mv_index_cdf_placeholder"
                       "[NUM_CTX_COL_MV_INDEX][CDF_SIZE(2)]",
                       0, &total_count, 0, mem_wanted, "Inter");

    if (!ibc) {
      cts_each_dim[0] = MV_JOINTS;
      optimize_cdf_table(&nmvc_cnts->amvd_joints_cnts[0], probsfile, 1,
                         cts_each_dim,
                         "static avm_cdf_prob amvd_joints_cdf_placeholder"
                         "[CDF_SIZE(MV_JOINTS)]",
                         0, &total_count, 0, mem_wanted, "Inter");
    }

    // Separate CDFs for row and columns of MVD
    for (int mvd_comp = 0; mvd_comp < 2; mvd_comp++) {
      if (!ibc) {
        cts_each_dim[0] = MAX_AMVD_INDEX;
        optimize_cdf_table(
            &nmvc_cnts->mvd_comp_cnts[mvd_comp].amvd_indices_cnts[0], probsfile,
            1, cts_each_dim,
            "static avm_cdf_prob amvd_indices_cdf_placeholder"
            "[CDF_SIZE(MAX_AMVD_INDEX)]",
            0, &total_count, 0, mem_wanted, "Inter");
      }
      cts_each_dim[0] = 2;
      optimize_cdf_table(&nmvc_cnts->mvd_comp_cnts[mvd_comp].sign_cnts[0],
                         probsfile, 1, cts_each_dim,
                         "static avm_cdf_prob sign_cdf_placeholder"
                         "[CDF_SIZE(2)]",
                         0, &total_count, 0, mem_wanted, "Inter");
    }  // for (int mvd_comp = 0; mvd_comp < 2; mvd_comp++)
  }  // for (int ibc = 0; ibc < 2; ibc++)

  cts_each_dim[0] = MAX_SEGMENTS;
  optimize_cdf_table(&fc.seg_tree_cnts[0], probsfile, 1, cts_each_dim,
                     "static avm_cdf_prob default_seg_tree_cdf"
                     "[CDF_SIZE(MAX_SEGMENTS)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = SEG_TEMPORAL_PRED_CTXS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.segment_pred_cnts[0][0], probsfile, 2, cts_each_dim,
                     "static avm_cdf_prob default_segment_pred_cdf"
                     "[SEG_TEMPORAL_PRED_CTXS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = SPATIAL_PREDICTION_PROBS;
  cts_each_dim[1] = MAX_SEGMENTS;
  optimize_cdf_table(&fc.spatial_pred_seg_tree_cnts[0][0], probsfile, 2,
                     cts_each_dim,
                     "static avm_cdf_prob default_spatial_pred_seg_tree_cdf"
                     "[SEG_TEMPORAL_PRED_CTXS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = EOB_TX_CTXS;
  cts_each_dim[1] = EXT_TX_SIZES;
  cts_each_dim[2] = 4;
  optimize_cdf_table(
      &fc.inter_ext_tx_short_side[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob "
      "default_inter_ext_tx_short_side_cdf[EOB_TX_CTXS][EXT_TX_SIZES]"
      "[CDF_SIZE(4)]",
      0, &total_count, 0, mem_wanted, "Transforms");

  cts_each_dim[0] = EXT_TX_SIZES;
  cts_each_dim[1] = 4;
  optimize_cdf_table(&fc.intra_ext_tx_short_side[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_intra_ext_tx_short_side_cdf[EXT_TX_SIZES]"
                     "[CDF_SIZE(4)]",
                     0, &total_count, 0, mem_wanted, "Transforms");

  cts_each_dim[0] = 2;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.tx_ext_32[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_tx_ext_32_cdf[2]"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Transforms");

  /* tx type */
  cts_each_dim[0] = EXT_TX_SETS_INTRA;
  cts_each_dim[1] = EXT_TX_SIZES;
  cts_each_dim[2] = TX_TYPES;
  int intra_ext_tx_types_each_ctx[EXT_TX_SETS_INTRA] = { 0, INTRA_TX_SET1,
                                                         INTRA_TX_SET2 };
  optimize_cdf_table_var_modes_3d(
      &fc.intra_ext_tx[0][0][0], probsfile, 3, cts_each_dim,
      intra_ext_tx_types_each_ctx,
      "static const avm_cdf_prob default_intra_ext_tx_cdf[EXT_TX_SETS_INTRA]"
      "[EXT_TX_SIZES][CDF_SIZE(TX_TYPES)]",
      0, &total_count, mem_wanted, "Transforms");

  cts_each_dim[0] = EXT_TX_SETS_INTER;
  cts_each_dim[1] = EOB_TX_CTXS;
  cts_each_dim[2] = EXT_TX_SIZES;
  cts_each_dim[3] = TX_TYPES;
  int inter_ext_tx_types_each_ctx[EXT_TX_SETS_INTER] = {
    0, INTER_TX_SET1, INTER_TX_SET2, INTER_TX_SET3, INTER_TX_SET4,
  };
  optimize_cdf_table_var_modes_4d(
      &fc.inter_ext_tx[0][0][0][0], probsfile, 4, cts_each_dim,
      inter_ext_tx_types_each_ctx,
      "static const avm_cdf_prob "
      "default_inter_ext_tx_cdf[EXT_TX_SETS_INTER][EOB_TX_CTXS]"
      "[EXT_TX_SIZES][CDF_SIZE(TX_TYPES)]",
      0, &total_count, mem_wanted, "Transforms");

  cts_each_dim[0] = 2;
  cts_each_dim[1] = EOB_TX_CTXS;
  cts_each_dim[2] = EXT_TX_SIZES;
  cts_each_dim[3] = 2;
  optimize_cdf_table(&fc.inter_tx_type_set[0][0][0][0], probsfile, 4,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_tx_type_set_cdf[2][EOB_TX_CTXS][EXT_TX_"
                     "SIZES][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Transforms");
  cts_each_dim[0] = 2;
  cts_each_dim[1] = EOB_TX_CTXS;
  cts_each_dim[2] = INTER_TX_TYPE_INDEX_COUNT;
  optimize_cdf_table(&fc.inter_tx_type_idx[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_tx_type_idx_cdf[2][EOB_TX_CTXS][CDF_SIZE("
                     "INTER_TX_TYPE_INDEX_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Transforms");
  cts_each_dim[0] = EOB_TX_CTXS;
  cts_each_dim[1] = INTER_TX_TYPE_OFFSET1_COUNT;
  optimize_cdf_table(&fc.inter_tx_type_offset_1[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_tx_type_offset_1_cdf[EOB_TX_CTXS][CDF_SIZE("
                     "INTER_TX_TYPE_OFFSET1_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Transforms");
  cts_each_dim[0] = EOB_TX_CTXS;
  cts_each_dim[1] = INTER_TX_TYPE_OFFSET2_COUNT;
  optimize_cdf_table(&fc.inter_tx_type_offset_2[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_tx_type_offset_2_cdf[EOB_TX_CTXS][CDF_SIZE("
                     "INTER_TX_TYPE_OFFSET1_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Transforms");
  /* Chroma from Luma */
  cts_each_dim[0] = CFL_TYPE_COUNT;
  optimize_cdf_table(&fc.cfl_index[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_cfl_index_cdf[CDF_SIZE(CFL_TYPE_COUNT)]",
                     0, &total_count, 0, mem_wanted, "Intra");
  cts_each_dim[0] = CFL_JOINT_SIGNS;
  optimize_cdf_table(&fc.cfl_sign[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)]",
                     0, &total_count, 0, mem_wanted, "Intra");
  cts_each_dim[0] = CFL_ALPHA_CONTEXTS;
  cts_each_dim[1] = CFL_ALPHABET_SIZE;
  optimize_cdf_table(&fc.cfl_alpha[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_cfl_alpha_cdf[CFL_ALPHA_CONTEXTS]"
                     "[CDF_SIZE(CFL_ALPHABET_SIZE)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* Interpolation filter */
  cts_each_dim[0] = SWITCHABLE_FILTER_CONTEXTS;
  cts_each_dim[1] = SWITCHABLE_FILTERS;
  optimize_cdf_table(&fc.switchable_interp[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_switchable_interp_cdf[SWITCHABLE_FILTER_CONTEXTS]"
                     "[CDF_SIZE(SWITCHABLE_FILTERS)]",
                     0, &total_count, 0, mem_wanted, "Filters");

  /* Single inter prediction mode */
  cts_each_dim[0] = INTER_MODE_CONTEXTS;
  cts_each_dim[1] = INTER_SINGLE_MODES;
  optimize_cdf_table(&fc.inter_single_mode[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_single_mode_cdf"
                     "[INTER_MODE_CONTEXTS][CDF_SIZE("
                     "INTER_SINGLE_MODES)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  // default_drl0_cdf_refmvbank[DRL_MODE_CONTEXTS][CDF_SIZE(2)]
  cts_each_dim[0] = 3;
  cts_each_dim[1] = DRL_MODE_CONTEXTS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.drl_mode[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_drl_cdf[3][DRL_MODE_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WARP_REF_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.warp_ref_cnts[0][0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_warp_ref_idx0_cdf[WARP_REF_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WARP_REF_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.warp_ref_cnts[1][0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_warp_ref_idx1_cdf[WARP_REF_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WARP_REF_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.warp_ref_cnts[2][0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_warp_ref_idx2_cdf[WARP_REF_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = JOINT_NEWMV_SCALE_FACTOR_CNT;
  optimize_cdf_table(
      &fc.jmvd_scale_mode_cnts[0], probsfile, 1, cts_each_dim,
      "static const avm_cdf_prob "
      "default_jmvd_scale_mode_cdf[CDF_SIZE(JOINT_NEWMV_SCALE_FACTOR_CNT)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = JOINT_AMVD_SCALE_FACTOR_CNT;
  optimize_cdf_table(
      &fc.jmvd_amvd_scale_mode_cnts[0], probsfile, 1, cts_each_dim,
      "static const avm_cdf_prob "
      "default_jmvd_amvd_scale_mode_cdf[CDF_SIZE(JOINT_AMVD_SCALE_FACTOR_CNT)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = MAX_CWP_CONTEXTS;
  cts_each_dim[1] = MAX_CWP_NUM - 1;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.cwp_idx_cnts[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob default_cwp_idx_cdf"
                     "[MAX_CWP_CONTEXTS][MAX_CWP_NUM - 1][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Optical flow MV refinement */
  cts_each_dim[0] = OPFL_MODE_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.use_optflow[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_use_optflow_cdf"
                     "[OPFL_MODE_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  /* ext_inter experiment */
  /* New compound mode */
  cts_each_dim[0] = NUM_CTX_IS_JOINT;
  cts_each_dim[1] = NUM_OPTIONS_IS_JOINT;
  optimize_cdf_table(&fc.inter_compound_mode_is_joint[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_compound_mode_cdf_is_joint"
                     "[NUM_CTX_IS_JOINT][CDF_SIZE("
                     "NUM_OPTIONS_IS_JOINT)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  cts_each_dim[0] = NUM_CTX_NON_JOINT_TYPE;
  cts_each_dim[1] = NUM_OPTIONS_NON_JOINT_TYPE;
  optimize_cdf_table(&fc.inter_compound_mode_non_joint_type[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_compound_mode_cdf_non_joint_type"
                     "[NUM_CTX_NON_JOINT_TYPE][CDF_SIZE("
                     "NUM_OPTIONS_NON_JOINT_TYPE)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  cts_each_dim[0] = NUM_CTX_JOINT_TYPE;
  cts_each_dim[1] = NUM_OPTIONS_JOINT_TYPE;
  optimize_cdf_table(&fc.inter_compound_mode_joint_type[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_compound_mode_cdf_joint_type"
                     "[NUM_CTX_JOINT_TYPE][CDF_SIZE("
                     "NUM_OPTIONS_JOINT_TYPE)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Compound mode context without considering NEW_NEARMV when two refs are the
   * same */
  cts_each_dim[0] = INTER_MODE_CONTEXTS;
  cts_each_dim[1] = INTER_COMPOUND_SAME_REFS_TYPES;
  optimize_cdf_table(&fc.inter_compound_mode_same_refs_cnt[0][0], probsfile, 2,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_inter_compound_mode_same_refs_cdf"
                     "[INTER_MODE_CONTEXTS][CDF_SIZE("
                     "INTER_COMPOUND_SAME_REFS_TYPES)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = NUM_AMVD_MODES;
  cts_each_dim[1] = AMVD_MODE_CONTEXTS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.amvd_mode[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_amvd_mode_cdf"
                     "[NUM_AMVD_MODES][AMVD_MODE_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Interintra */
  cts_each_dim[0] = BLOCK_SIZE_GROUPS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.interintra[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = BLOCK_SIZE_GROUPS;
  cts_each_dim[1] = INTERINTRA_MODES;
  optimize_cdf_table(&fc.interintra_mode[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE("
                     "INTERINTRA_MODES)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.wedge_interintra[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_wedge_interintra_cdf[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Compound type */
  cts_each_dim[0] = COMPOUND_TYPES - 1;
  optimize_cdf_table(&fc.compound_type[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob default_compound_type_cdf"
                     "[CDF_SIZE(COMPOUND_TYPES - 1)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WEDGE_QUADS;
  optimize_cdf_table(&fc.wedge_quad_cnt[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_wedge_quad_cdf[CDF_SIZE(WEDGE_QUADS)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WEDGE_QUADS;
  cts_each_dim[1] = QUAD_WEDGE_ANGLES;
  optimize_cdf_table(&fc.wedge_angle_cnt[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_wedge_angle_cdf[CDF_SIZE(WEDGE_QUADS)][CDF_SIZE("
                     "QUAD_WEDGE_ANGLES)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  cts_each_dim[0] = NUM_WEDGE_DIST;
  optimize_cdf_table(&fc.wedge_dist_cnt[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_wedge_dist_cdf[CDF_SIZE(NUM_WEDGE_DIST)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = NUM_WEDGE_DIST - 1;
  optimize_cdf_table(&fc.wedge_dist2_cnt[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_wedge_dist_cdf2[CDF_SIZE(NUM_WEDGE_DIST - 1)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = NUM_REFINEMV_CTX;
  cts_each_dim[1] = REFINEMV_NUM_MODES;
  optimize_cdf_table(&fc.refinemv_flag_cnts[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_refinemv_flag_cdf[NUM_REFINEMV_CTX][CDF_SIZE("
                     "REFINEMV_NUM_MODES)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 3;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.skip_drl_cnts[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_skip_drl_cdf[3][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 3;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.tip_drl_mode[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_tip_drl_cdf[3][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = WARPMV_MODE_CONTEXT;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.inter_warp_cnts[0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_inter_warp_mode_cdf[WARPMV_MODE_CONTEXT][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.is_warpmv_or_warp_newmv_cnt[0], probsfile, 1,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_is_warpmv_or_warp_newmv_cdf[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* motion_var and warped_motion experiments */

  cts_each_dim[0] = WARP_CAUSAL_MODE_CTX;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.warp_causal_cnt[0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_warp_causal_cdf[WARP_CAUSAL_MODE_CTX]CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 2;
  cts_each_dim[1] = WARP_DELTA_NUMSYMBOLS_LOW;
  optimize_cdf_table(&fc.warp_delta_param[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_warp_delta_param_cdf"
                     "[2][CDF_SIZE(WARP_DELTA_NUMSYMBOLS_LOW)]",
                     0, &total_count, 0, mem_wanted, "Inter");
#if CONFIG_WARP_PRECISION
  cts_each_dim[0] = 2;
  cts_each_dim[1] = WARP_DELTA_NUMSYMBOLS_HIGH;
  optimize_cdf_table(
      &fc.warp_delta_param_high[0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob default_warp_delta_param_high_cdf"
      "[2][CDF_SIZE(WARP_DELTA_NUMSYMBOLS_HIGH)]",
      0, &total_count, 0, mem_wanted, "Inter");
#endif  // CONFIG_WARP_PRECISION

  cts_each_dim[0] = WARP_EXTEND_CTX;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.warp_extend[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_warp_extend_cdf[WARP_EXTEND_CTX]CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.warpmv_with_mvd_flag[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_warpmv_with_mvd_flag_cdf[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Bawp flag */
  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.bawp[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_bawp_cdf[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  /* Intra/inter flag */
  cts_each_dim[0] = INTRA_INTER_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.intra_inter[0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_intra_inter_cdf[INTRA_INTER_CONTEXTS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Inter");
  /* Single/comp ref flag */
  cts_each_dim[0] = COMP_INTER_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.comp_inter[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* Reference frame (single ref) */
  cts_each_dim[0] = REF_CONTEXTS;
  cts_each_dim[1] = INTER_REFS_PER_FRAME - 1;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.single_ref[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_single_ref_cdf[REF_CONTEXTS][INTER_REFS_PER_"
                     "FRAME - 1][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* ext_refs experiment */
  cts_each_dim[0] = REF_CONTEXTS;
  cts_each_dim[1] = INTER_REFS_PER_FRAME - 1;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.comp_ref0[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_comp_ref0_cdf[REF_CONTEXTS]"
                     "[INTER_REFS_PER_FRAME - 1]"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");
  cts_each_dim[0] = REF_CONTEXTS;
  cts_each_dim[1] = COMPREF_BIT_TYPES;
  cts_each_dim[2] = INTER_REFS_PER_FRAME - 1;
  cts_each_dim[3] = 2;
  optimize_cdf_table(&fc.comp_ref1[0][0][0][0], probsfile, 4, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_comp_ref1_cdf[REF_CONTEXTS][COMPREF_BIT_TYPES]"
                     "[INTER_REFS_PER_FRAME - 1]"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  cts_each_dim[0] = PALETTE_ROW_FLAG_CONTEXTS;
  cts_each_dim[1] = 3;
  optimize_cdf_table(&fc.identity_row_y_cnts[0][0], probsfile, 2, cts_each_dim,
                     "const avm_cdf_prob default_identity_row_cdf_y"
                     "[PALETTE_ROW_FLAG_CONTEXTS][CDF_SIZE(3)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = PALETTE_ROW_FLAG_CONTEXTS;
  cts_each_dim[1] = 3;
  optimize_cdf_table(&fc.identity_row_uv_cnts[0][0], probsfile, 2, cts_each_dim,
                     "const avm_cdf_prob default_identity_row_cdf_uv"
                     "[PALETTE_ROW_FLAG_CONTEXTS][CDF_SIZE(3)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  /* palette */
  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.palette_y_size[0], probsfile, 1, cts_each_dim,
                     "const avm_cdf_prob default_palette_y_size_cdf"
                     "[CDF_SIZE(PALETTE_SIZES)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  optimize_cdf_table(&fc.palette_uv_size[0], probsfile, 1, cts_each_dim,
                     "const avm_cdf_prob default_palette_uv_size_cdf"
                     "[CDF_SIZE(PALETTE_SIZES)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  optimize_cdf_table(&fc.palette_y_mode[0], probsfile, 1, cts_each_dim,
                     "const avm_cdf_prob default_palette_y_mode_cdf"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  optimize_cdf_table(&fc.palette_uv_mode[0], probsfile, 1, cts_each_dim,
                     "const avm_cdf_prob default_palette_uv_mode_cdf"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = PALETTE_SIZES;
  cts_each_dim[1] = PALETTE_COLOR_INDEX_CONTEXTS;
  cts_each_dim[2] = PALETTE_COLORS;
  int palette_color_indexes_each_ctx[PALETTE_SIZES] = { 2, 3, 4, 5, 6, 7, 8 };
  optimize_cdf_table_var_modes_3d(
      &fc.palette_y_color_index[0][0][0], probsfile, 3, cts_each_dim,
      palette_color_indexes_each_ctx,
      "const avm_cdf_prob default_palette_y_color_index_cdf[PALETTE_SIZES]"
      "[PALETTE_COLOR_INDEX_CONTEXTS][CDF_SIZE(PALETTE_COLORS)]",
      0, &total_count, mem_wanted, "Coefficients");

  cts_each_dim[0] = PALETTE_SIZES;
  cts_each_dim[1] = PALETTE_COLOR_INDEX_CONTEXTS;
  cts_each_dim[2] = PALETTE_COLORS;
  optimize_cdf_table_var_modes_3d(
      &fc.palette_uv_color_index[0][0][0], probsfile, 3, cts_each_dim,
      palette_color_indexes_each_ctx,
      "const avm_cdf_prob default_palette_uv_color_index_cdf[PALETTE_SIZES]"
      "[PALETTE_COLOR_INDEX_CONTEXTS][CDF_SIZE(PALETTE_COLORS)]",
      0, &total_count, mem_wanted, "Coefficients");

  /* Transform size */
  cts_each_dim[0] = FSC_MODES;
  cts_each_dim[1] = 2;
  cts_each_dim[2] = TXFM_SPLIT_GROUP;
  cts_each_dim[3] = 2;
  optimize_cdf_table(&fc.txfm_do_partition[0][0][0][0], probsfile, 4,
                     cts_each_dim,
                     "static const avm_cdf_prob default_txfm_do_partition_cdf"
                     "[FSC_MODES][2][TXFM_SPLIT_GROUP][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Partitions");

  cts_each_dim[0] = FSC_MODES;
  cts_each_dim[1] = 2;
  cts_each_dim[2] = TX_PARTITION_TYPE_NUM_VERT_AND_HORZ;
  cts_each_dim[3] = TX_PARTITION_TYPE_NUM;
  optimize_cdf_table(
      &fc.txfm_4way_partition_type[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob default_txfm_4way_partition_type_cdf"
      "[FSC_MODES][2][TX_PARTITION_TYPE_NUM_VERT_AND_HORZ]"
      "[CDF_SIZE(TX_PARTITION_TYPE_NUM)]",
      0, &total_count, 0, mem_wanted, "Partitions");

  cts_each_dim[0] = FSC_MODES;
  cts_each_dim[1] = 2;
  cts_each_dim[2] = TX_PARTITION_TYPE_NUM_VERT_OR_HORZ - 1;
  cts_each_dim[3] = 2;
  optimize_cdf_table(
      &fc.txfm_2or3_way_partition_type[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob default_txfm_2or3_way_partition_type_cdf"
      "[FSC_MODES][2][TX_PARTITION_TYPE_NUM_VERT_OR_HORZ - "
      "1][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Partitions");

  /* Skip flag */
  cts_each_dim[0] = SKIP_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.skip_txfm[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_skip_txfm_cdfs[SKIP_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Coefficients");

  /* Skip mode flag */
  cts_each_dim[0] = SKIP_MODE_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.skip_mode_cnts[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_skip_mode_cdfs[SKIP_MODE_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* TIP ref flag */
  cts_each_dim[0] = TIP_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.tip_ref[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_tip_cdf[TIP_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* TIP prediction mode flag */
  cts_each_dim[0] = TIP_PRED_MODES;
  optimize_cdf_table(&fc.tip_pred_mode_cnt[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_tip_pred_mode_cdf[CDF_SIZE(TIP_PRED_MODES)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* joint compound group index */
  cts_each_dim[0] = COMP_GROUP_IDX_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.comp_group_idx[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_comp_group_idx_cdfs"
                     "[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Inter");

  /* intrabc */
  cts_each_dim[0] = INTRABC_CONTEXTS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.intrabc[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_intrabc_cdf[INTRABC_CONTEXTS][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* intrabc mode flag*/
  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.intrabc_mode[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_intrabc_mode_cdf[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Intra");

#if CONFIG_MORPH_PRED
  cts_each_dim[0] = 3;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.morph_pred_count[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_morph_pred_cdf[3][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Intra");
#endif  // CONFIG_MORPH_PRED

  cts_each_dim[0] = 3;
  cts_each_dim[1] = CCSO_CONTEXT;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.default_ccso_cnts[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_ccso_cdf[3][CCSO_CONTEXT][CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Filters");

  cts_each_dim[0] = CDEF_STRENGTH_INDEX0_CTX;
  cts_each_dim[1] = 2;
  optimize_cdf_table(
      &fc.cdef_strength_index0_cnts[0][0], probsfile, 2, cts_each_dim,
      "static const avm_cdf_prob "
      "default_cdef_strength_index0_cdf[CDEF_STRENGTH_INDEX0_CTX][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Filters");

  cts_each_dim[0] = CDEF_STRENGTHS_NUM - 1;
  cts_each_dim[1] = CDEF_STRENGTHS_NUM;
  int cdef_size_each_ctx[CDEF_STRENGTHS_NUM - 1] = { 2, 3, 4, 5, 6, 7 };
  optimize_cdf_table_var_modes_2d(
      &fc.cdef_cnts[0][0], probsfile, 2, cts_each_dim, cdef_size_each_ctx,
      "static const avm_cdf_prob "
      "default_cdef_cdf[CDEF_STRENGTHS_NUM - 1][CDF_SIZE(CDEF_STRENGTHS_NUM)]",
      0, &total_count, mem_wanted, "Filters");

  cts_each_dim[0] = MAX_LR_FLEX_SWITCHABLE_BITS;
  cts_each_dim[1] = MAX_MB_PLANE;
  cts_each_dim[2] = 2;
  optimize_cdf_table(
      &fc.switchable_flex_restore_cnts[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob "
      "default_switchable_flex_restore_cdf[MAX_LR_FLEX_SWITCHABLE_BITS]"
      "[MAX_MB_PLANE][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Filters");
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = DIP_CTXS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(
      &fc.intra_dip[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob "
      "default_intra_dip_cdf[TOKEN_CDF_Q_CTXS][DIP_CTXS][CDF_SIZE(2)]",
      0, &total_count, 0, mem_wanted, "Intra");
  cts_each_dim[0] = 6;
  optimize_cdf_table(&fc.intra_dip_mode_n6[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_intra_dip_mode_n6_cdf[CDF_SIZE(6)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* forward skip coding flag */
  cts_each_dim[0] = FSC_MODE_CONTEXTS;
  cts_each_dim[1] = FSC_BSIZE_CONTEXTS;
  cts_each_dim[2] = FSC_MODES;
  optimize_cdf_table(&fc.fsc_mode[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "default_fsc_mode_cdf[FSC_MODE_CONTEXTS]"
                     "[FSC_BSIZE_CONTEXTS][CDF_SIZE(FSC_MODES)]",
                     0, &total_count, 0, mem_wanted, "Intra");

  /* restoration type */
  cts_each_dim[0] = WIENERNS_4PART_CTX_MAX;
  cts_each_dim[1] = 4;
  optimize_cdf_table(&fc.wienerns_4part_cnts[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_wienerns_4part_cdf"
                     "[WIENERNS_4PART_CTX_MAX][CDF_SIZE(4)]",
                     0, &total_count, 0, mem_wanted, "Filters");
  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.wienerns_restore[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob default_wienerns_restore_cdf"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Filters");
  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.pc_wiener_restore[0], probsfile, 1, cts_each_dim,
                     "static const avm_cdf_prob default_pc_wiener_restore_cdf"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Filters");

  cts_each_dim[0] = 2;
  optimize_cdf_table(&fc.wienerns_length[0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob default_wienerns_length_cdf"
                     "[CDF_SIZE(2)]",
                     0, &total_count, 0, mem_wanted, "Filters");

  /* transform coding */
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = TXB_SKIP_CONTEXTS;
  cts_each_dim[3] = 2;
  optimize_cdf_table(&fc.txb_skip[0][0][0][0], probsfile, 4, cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_txb_skip_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES]"
                     "[TXB_SKIP_CONTEXTS][CDF_SIZE(2)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  /* forward skip sign bit */
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = FSC_TX_SIZE_CONTEXTS;
  cts_each_dim[2] = IDTX_SIGN_CONTEXTS;
  cts_each_dim[3] = 2;
  optimize_cdf_table(&fc.idtx_sign[0][0][0][0], probsfile, 4, cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_idtx_sign_cdfs[TOKEN_CDF_Q_CTXS]"
                     "[FSC_TX_SIZE_CONTEXTS][IDTX_SIGN_CONTEXTS][CDF_SIZE(2)]",
                     1, &total_count, 72, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = FSC_TX_SIZE_CONTEXTS;
  cts_each_dim[2] = SIG_COEF_CONTEXTS_BOB;
  cts_each_dim[3] = NUM_BASE_LEVELS + 1;
  optimize_cdf_table(
      &fc.coeff_base_bob_multi[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_bob_multi_cdfs"
      "[TOKEN_CDF_Q_CTXS][FSC_TX_SIZE_CONTEXTS][SIG_COEF_CONTEXTS_BOB]"
      "[CDF_SIZE(NUM_BASE_LEVELS + 1)]",
      1, &total_count, 24, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = V_TXB_SKIP_CONTEXTS;
  cts_each_dim[2] = 2;
  optimize_cdf_table(&fc.v_txb_skip[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_v_txb_skip_cdfs[TOKEN_CDF_Q_CTXS]"
                     "[V_TXB_SKIP_CONTEXTS][CDF_SIZE(2)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = 2;
  optimize_cdf_table(&fc.eob_extra[0][0], probsfile, 2, cts_each_dim,
                     "static const avm_cdf_prob av2_default_eob_extra_cdfs"
                     "[TOKEN_CDF_Q_CTXS]"
                     "[CDF_SIZE(2)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 6;
  optimize_cdf_table(
      &fc.eob_multi16[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi16_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 6)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 5;
  optimize_cdf_table(
      &fc.eob_multi32[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi32_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 5)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 4;
  optimize_cdf_table(
      &fc.eob_multi64[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi64_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 4)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 3;
  optimize_cdf_table(
      &fc.eob_multi128[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi128_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 3)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 2;
  optimize_cdf_table(
      &fc.eob_multi256[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi256_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 2)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS - 1;
  optimize_cdf_table(
      &fc.eob_multi512[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi512_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS - 1)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = EOB_PLANE_CTXS;
  cts_each_dim[2] = EOB_MAX_SYMS;
  optimize_cdf_table(
      &fc.eob_multi1024[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_eob_multi1024_cdfs"
      "[TOKEN_CDF_Q_CTXS][EOB_PLANE_CTXS][CDF_SIZE(EOB_MAX_SYMS)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  // LF Base, BR
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = LF_SIG_COEF_CONTEXTS_UV;
  cts_each_dim[2] = LF_BASE_SYMBOLS;
  int dq_minus_entries_uv = LF_SIG_COEF_CONTEXTS_UV * (LF_BASE_SYMBOLS - 1);
  optimize_cdf_table(
      &fc.coeff_base_lf_multi_uv[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_lf_multi_uv_cdfs"
      "[TOKEN_CDF_Q_CTXS][LF_SIG_COEF_CONTEXTS_UV][CDF_SIZE(LF_BASE_"
      "SYMBOLS)]",
      1, &total_count, dq_minus_entries_uv, mem_wanted, "Coefficients");

  // HF Base, BR
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = SIG_COEF_CONTEXTS_UV;
  cts_each_dim[2] = NUM_BASE_LEVELS + 2;
  dq_minus_entries_uv = SIG_COEF_CONTEXTS_UV * (NUM_BASE_LEVELS + 2 - 1);
  optimize_cdf_table(
      &fc.coeff_base_multi_uv[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_multi_uv_cdfs"
      "[TOKEN_CDF_Q_CTXS][SIG_COEF_CONTEXTS_UV][CDF_SIZE(NUM_BASE_"
      "LEVELS + 2)]",
      1, &total_count, dq_minus_entries_uv, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = LEVEL_CONTEXTS_UV;
  cts_each_dim[2] = BR_CDF_SIZE;
  optimize_cdf_table(&fc.coeff_lps_multi_uv[0][0][0], probsfile, 3,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_coeff_lps_multi_uv_cdfs[TOKEN_CDF_Q_CTXS]"
                     "[LEVEL_CONTEXTS_UV][CDF_SIZE(BR_CDF_SIZE)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  // LF, HF EOB
  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = SIG_COEF_CONTEXTS_EOB;
  cts_each_dim[2] = LF_BASE_SYMBOLS - 1;
  optimize_cdf_table(
      &fc.coeff_base_lf_eob_multi_uv[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_lf_eob_multi_uv_cdfs"
      "[TOKEN_CDF_Q_CTXS][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(LF_BASE_SYMBOLS - "
      "1)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = SIG_COEF_CONTEXTS_EOB;
  cts_each_dim[2] = NUM_BASE_LEVELS + 1;
  optimize_cdf_table(
      &fc.coeff_base_eob_multi_uv[0][0][0], probsfile, 3, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_eob_multi_uv_cdfs"
      "[TOKEN_CDF_Q_CTXS][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(NUM_BASE_LEVELS + "
      "1)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = COEFF_BASE_PH_CONTEXTS;
  cts_each_dim[2] = NUM_BASE_LEVELS + 2;
  optimize_cdf_table(&fc.coeff_base_ph_multi[0][0][0], probsfile, 3,
                     cts_each_dim,
                     "const avm_cdf_prob "
                     "av2_default_coeff_base_ph_cdfs[TOKEN_CDF_Q_CTXS][COEFF_"
                     "BASE_PH_CONTEXTS][CDF_SIZE(NUM_BASE_LEVELS + 2)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = LF_SIG_COEF_CONTEXTS;
  cts_each_dim[3] = TCQ_CTXS;
  cts_each_dim[4] = LF_BASE_SYMBOLS;
  int dq_minus_entries_lf =
      LF_SIG_COEF_CONTEXTS_1D * TX_SIZES * (LF_BASE_SYMBOLS - 1);
  optimize_cdf_table(
      &fc.coeff_base_lf_multi[0][0][0][0][0], probsfile, 5, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_lf_multi_cdfs"
      "[TOKEN_CDF_Q_CTXS][TX_SIZES][LF_SIG_COEF_CONTEXTS][TCQ_CTXS]"
      "[CDF_SIZE(LF_BASE_SYMBOLS)]",
      1, &total_count, dq_minus_entries_lf, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = SIG_COEF_CONTEXTS_EOB;
  cts_each_dim[3] = LF_BASE_SYMBOLS - 1;
  optimize_cdf_table(
      &fc.coeff_base_lf_eob_multi[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_lf_eob_multi_cdfs"
      "[TOKEN_CDF_Q_CTXS][TX_SIZES][SIG_COEF_CONTEXTS_EOB]"
      "[CDF_SIZE(LF_BASE_SYMBOLS - 1)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = LF_LEVEL_CONTEXTS;
  cts_each_dim[2] = BR_CDF_SIZE;
  optimize_cdf_table(&fc.coeff_lps_lf_multi[0][0][0], probsfile, 3,
                     cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_coeff_lps_lf_multi_cdfs[TOKEN_CDF_Q_CTXS]"
                     "[LF_LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = LEVEL_CONTEXTS;
  cts_each_dim[2] = BR_CDF_SIZE;
  optimize_cdf_table(&fc.coeff_lps_multi[0][0][0], probsfile, 3, cts_each_dim,
                     "static const avm_cdf_prob "
                     "av2_default_coeff_lps_multi_cdfs[TOKEN_CDF_Q_CTXS]"
                     "[LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE)]",
                     1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = SIG_COEF_CONTEXTS;
  cts_each_dim[3] = TCQ_CTXS;
  cts_each_dim[4] = NUM_BASE_LEVELS + 2;
  int dq_minus_entries_def = 5 * TX_SIZES * (NUM_BASE_LEVELS + 2 - 1);
  optimize_cdf_table(
      &fc.coeff_base_multi[0][0][0][0][0], probsfile, 5, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_multi_cdfs"
      "[TOKEN_CDF_Q_CTXS][TX_SIZES][SIG_COEF_CONTEXTS][TCQ_CTXS]"
      "[CDF_SIZE(NUM_BASE_LEVELS + 2)]",
      1, &total_count, dq_minus_entries_def, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = FSC_TX_SIZE_CONTEXTS;
  cts_each_dim[2] = IDTX_LEVEL_CONTEXTS;
  cts_each_dim[3] = BR_CDF_SIZE;
  optimize_cdf_table(
      &fc.coeff_lps_multi_skip[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob "
      "av2_default_coeff_lps_multi_cdfs_idtx"
      "[TOKEN_CDF_Q_CTXS][FSC_TX_SIZE_CONTEXTS][IDTX_LEVEL_CONTEXTS]"
      "[CDF_SIZE(BR_CDF_SIZE)]",
      1, &total_count, 196, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = FSC_TX_SIZE_CONTEXTS;
  cts_each_dim[2] = IDTX_SIG_COEF_CONTEXTS;
  cts_each_dim[3] = NUM_BASE_LEVELS + 2;
  optimize_cdf_table(
      &fc.coeff_base_multi_skip[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_multi_cdfs_idtx"
      "[TOKEN_CDF_Q_CTXS][FSC_TX_SIZE_CONTEXTS][IDTX_SIG_COEF_CONTEXTS]"
      "[CDF_SIZE(NUM_BASE_LEVELS + 2)]",
      1, &total_count, 196, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = TX_SIZES;
  cts_each_dim[2] = SIG_COEF_CONTEXTS_EOB;
  cts_each_dim[3] = NUM_BASE_LEVELS + 1;
  optimize_cdf_table(
      &fc.coeff_base_eob_multi[0][0][0][0], probsfile, 4, cts_each_dim,
      "static const avm_cdf_prob av2_default_coeff_base_eob_multi_cdfs"
      "[TOKEN_CDF_Q_CTXS][TX_SIZES][SIG_COEF_CONTEXTS_EOB]"
      "[CDF_SIZE(NUM_BASE_LEVELS + 1)]",
      1, &total_count, 0, mem_wanted, "Coefficients");

  cts_each_dim[0] = TOKEN_CDF_Q_CTXS;
  cts_each_dim[1] = PLANE_TYPES;
  cts_each_dim[2] = DC_SIGN_GROUPS;
  cts_each_dim[3] = DC_SIGN_CONTEXTS;
  cts_each_dim[4] = 2;
  optimize_cdf_table(
      &fc.dc_sign[0][0][0][0][0], probsfile, 5, cts_each_dim,
      "static const avm_cdf_prob av2_default_dc_sign_cdfs"
      "[TOKEN_CDF_Q_CTXS][PLANE_TYPES][DC_SIGN_GROUPS][DC_SIGN_CONTEXTS]"
      "[CDF_SIZE(2)]",
      1, &total_count, 0, mem_wanted, "Coefficients");
  if (mem_wanted) {
    printf("Total RAM in bits %d \n", total_count);
  } else {
    if (statsfile != NULL) {
      fclose(statsfile);
    }
    if (logfile != NULL) {
      fclose(logfile);
    }
    if (probsfile != NULL) {
      fclose(probsfile);
    }
  }
  return 0;
}
