/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
│                                                                              │
│ Permission to use, copy, modify, and/or distribute this software for         │
│ any purpose with or without fee is hereby granted, provided that the         │
│ above copyright notice and this permission notice appear in all copies.      │
│                                                                              │
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
│ PERFORMANCE OF THIS SOFTWARE.                                                │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/core.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/mem/gc.internal.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"

TEST(unalaw, outOfRange_modulo256) {
  EXPECT_EQ(880, unalaw(-2));
  EXPECT_EQ(880, unalaw(-2 & 255));
  EXPECT_EQ(5248, unalaw(-127));
  EXPECT_EQ(5248, unalaw(-127 & 255));
}

TEST(alaw, test) {
  int i;
  static const int V[][2] = {
      {42, -32768}, {42, -32691}, {42, -32376}, {42, -32328}, {42, -32235},
      {42, -31923}, {43, -31645}, {43, -31328}, {43, -31147}, {43, -31129},
      {43, -31110}, {43, -31092}, {43, -30824}, {43, -30728}, {40, -30473},
      {40, -30297}, {40, -30074}, {40, -30013}, {40, -29972}, {40, -29830},
      {40, -29707}, {41, -29595}, {41, -29384}, {41, -29235}, {41, -28959},
      {41, -28947}, {41, -28816}, {41, -28708}, {46, -28580}, {46, -28538},
      {46, -28483}, {46, -28256}, {46, -27976}, {46, -27829}, {47, -27644},
      {47, -27471}, {47, -27189}, {47, -27042}, {47, -26999}, {47, -26707},
      {44, -26610}, {44, -26464}, {44, -26145}, {44, -25897}, {44, -25722},
      {44, -25638}, {45, -25556}, {45, -25310}, {45, -25310}, {45, -25083},
      {45, -24986}, {45, -24920}, {45, -24676}, {45, -24650}, {34, -24565},
      {34, -24531}, {34, -24349}, {34, -24203}, {34, -24073}, {34, -23997},
      {34, -23804}, {34, -23714}, {34, -23654}, {35, -23435}, {35, -23370},
      {35, -23060}, {35, -22908}, {35, -22784}, {32, -22493}, {32, -22409},
      {32, -22342}, {32, -22018}, {32, -21952}, {32, -21866}, {32, -21699},
      {33, -21436}, {33, -21161}, {33, -21041}, {33, -20744}, {33, -20711},
      {38, -20430}, {38, -20300}, {38, -20162}, {38, -19939}, {38, -19820},
      {38, -19765}, {38, -19576}, {39, -19427}, {39, -19268}, {39, -19098},
      {39, -19049}, {39, -18888}, {39, -18845}, {39, -18803}, {39, -18528},
      {36, -18424}, {36, -18119}, {36, -17808}, {36, -17685}, {36, -17589},
      {36, -17481}, {37, -17397}, {37, -17190}, {37, -17119}, {37, -16916},
      {37, -16910}, {37, -16747}, {37, -16706}, {37, -16682}, {37, -16406},
      {58, -16311}, {58, -16292}, {58, -16187}, {58, -16103}, {59, -15864},
      {59, -15753}, {59, -15520}, {59, -15373}, {56, -15289}, {56, -15020},
      {57, -14748}, {57, -14604}, {57, -14538}, {62, -14315}, {62, -14236},
      {62, -14046}, {62, -14043}, {62, -13985}, {63, -13664}, {63, -13453},
      {60, -13143}, {60, -13099}, {60, -13044}, {60, -12802}, {61, -12538},
      {61, -12476}, {61, -12411}, {61, -12340}, {50, -12073}, {51, -11760},
      {51, -11442}, {48, -11133}, {48, -11102}, {48, -10928}, {48, -10791},
      {49, -10697}, {49, -10534}, {49, -10331}, {49, -10257}, {54, -9991},
      {54, -9732},  {55, -9714},  {55, -9544},  {55, -9389},  {55, -9385},
      {55, -9245},  {52, -9102},  {52, -8838},  {53, -8534},  {53, -8405},
      {53, -8321},  {53, -8232},  {10, -8101},  {11, -7879},  {8, -7650},
      {8, -7630},   {8, -7616},   {8, -7559},   {8, -7442},   {9, -7305},
      {9, -7267},   {14, -7141},  {14, -6962},  {15, -6838},  {15, -6734},
      {12, -6502},  {12, -6479},  {13, -6162},  {2, -6142},   {2, -5933},
      {3, -5648},   {0, -5523},   {1, -5291},   {1, -5149},   {6, -4868},
      {7, -4807},   {7, -4677},   {4, -4556},   {4, -4484},   {4, -4353},
      {5, -4149},   {26, -4048},  {27, -3935},  {24, -3720},  {31, -3447},
      {31, -3392},  {28, -3313},  {29, -3106},  {19, -2891},  {19, -2838},
      {16, -2745},  {17, -2663},  {22, -2481},  {20, -2184},  {21, -2084},
      {105, -1847}, {105, -1808}, {98, -1520},  {99, -1471},  {103, -1168},
      {126, -876},  {112, -673},  {119, -578},  {68, -287},   {88, -220},
      {81, -76},    {85, -13},    {213, 13},    {218, 253},   {197, 256},
      {245, 540},   {246, 634},   {248, 931},   {229, 1063},  {229, 1066},
      {225, 1305},  {227, 1451},  {239, 1715},  {239, 1725},  {235, 1982},
      {149, 2122},  {148, 2205},  {148, 2219},  {150, 2539},  {145, 2679},
      {144, 2752},  {146, 3025},  {156, 3239},  {156, 3239},  {159, 3346},
      {153, 3633},  {153, 3649},  {153, 3704},  {152, 3799},  {152, 3799},
      {154, 4089},  {132, 4369},  {132, 4606},  {135, 4712},  {134, 5031},
      {129, 5183},  {129, 5211},  {128, 5396},  {128, 5535},  {131, 5761},
      {131, 5821},  {131, 5878},  {130, 5970},  {141, 6156},  {141, 6206},
      {141, 6307},  {140, 6607},  {143, 6661},  {142, 6915},  {142, 7126},
      {137, 7296},  {137, 7391},  {139, 7684},  {139, 7707},  {139, 7736},
      {139, 7820},  {138, 7982},  {181, 8300},  {181, 8335},  {181, 8582},
      {181, 8655},  {180, 8850},  {180, 8961},  {180, 9008},  {183, 9301},
      {183, 9597},  {183, 9605},  {183, 9697},  {182, 9921},  {182, 10143},
      {182, 10223}, {177, 10477}, {177, 10749}, {176, 10951}, {176, 11121},
      {179, 11321}, {179, 11620}, {179, 11645}, {179, 11708}, {179, 11716},
      {179, 11763}, {178, 11949}, {178, 12271}, {178, 12287}, {189, 12514},
      {189, 12561}, {189, 12575}, {188, 12844}, {188, 13162}, {191, 13337},
      {191, 13631}, {190, 13957}, {190, 14175}, {190, 14270}, {185, 14411},
      {185, 14720}, {184, 14975}, {184, 15047}, {184, 15135}, {184, 15246},
      {187, 15477}, {187, 15491}, {187, 15581}, {187, 15646}, {187, 15785},
      {186, 15983}, {186, 15993}, {186, 16169}, {186, 16178}, {186, 16355},
      {165, 16536}, {165, 16850}, {165, 17132}, {165, 17366}, {164, 17593},
      {164, 17667}, {164, 17679}, {164, 17765}, {164, 17771}, {164, 17807},
      {164, 17843}, {164, 18079}, {164, 18325}, {167, 18625}, {167, 18931},
      {167, 19160}, {167, 19381}, {166, 19677}, {166, 19805}, {166, 19972},
      {166, 20140}, {166, 20404}, {161, 20515}, {161, 20767}, {161, 21071},
      {161, 21339}, {161, 21369}, {161, 21411}, {160, 21685}, {160, 21701},
      {160, 21963}, {160, 22109}, {160, 22187}, {160, 22197}, {160, 22378},
      {163, 22670}, {163, 22990}, {163, 23063}, {163, 23156}, {163, 23158},
      {163, 23459}, {163, 23471}, {162, 23792}, {162, 23955}, {162, 24163},
      {162, 24300}, {173, 24589}, {173, 24722}, {173, 24865}, {173, 25135},
      {173, 25225}, {173, 25341}, {173, 25480}, {172, 25653}, {172, 25779},
      {172, 26018}, {172, 26257}, {172, 26576}, {175, 26894}, {175, 27191},
      {175, 27294}, {175, 27468}, {175, 27498}, {175, 27575}, {175, 27644},
      {174, 27723}, {174, 27764}, {174, 27954}, {174, 27969}, {174, 27979},
      {174, 28059}, {174, 28124}, {174, 28330}, {174, 28408}, {174, 28627},
      {169, 28704}, {169, 28880}, {169, 29014}, {169, 29095}, {169, 29301},
      {169, 29429}, {169, 29515}, {169, 29520}, {169, 29661}, {168, 29812},
      {168, 30030}, {168, 30157}, {168, 30405}, {168, 30476}, {171, 30760},
      {171, 30883}, {171, 31029}, {171, 31249}, {171, 31482}, {171, 31578},
      {171, 31696}, {170, 31902}, {170, 32116}, {170, 32440}, {170, 32472},
      {170, 32711},
  };
  for (i = 0; i < ARRAYLEN(V); ++i) {
    ASSERT_EQ(V[i][0], alaw(V[i][1]));
  }
}

TEST(unalaw, test) {
  int i;
  static const int V[][2] = {
      {-5504, 0},   {-5248, 1},   {-6016, 2},   {-5760, 3},   {-4480, 4},
      {-4224, 5},   {-4992, 6},   {-4736, 7},   {-7552, 8},   {-7296, 9},
      {-8064, 10},  {-7808, 11},  {-6528, 12},  {-6272, 13},  {-7040, 14},
      {-6784, 15},  {-2752, 16},  {-2624, 17},  {-3008, 18},  {-2880, 19},
      {-2240, 20},  {-2112, 21},  {-2496, 22},  {-2368, 23},  {-3776, 24},
      {-3648, 25},  {-4032, 26},  {-3904, 27},  {-3264, 28},  {-3136, 29},
      {-3520, 30},  {-3392, 31},  {-22016, 32}, {-20992, 33}, {-24064, 34},
      {-23040, 35}, {-17920, 36}, {-16896, 37}, {-19968, 38}, {-18944, 39},
      {-30208, 40}, {-29184, 41}, {-32256, 42}, {-31232, 43}, {-26112, 44},
      {-25088, 45}, {-28160, 46}, {-27136, 47}, {-11008, 48}, {-10496, 49},
      {-12032, 50}, {-11520, 51}, {-8960, 52},  {-8448, 53},  {-9984, 54},
      {-9472, 55},  {-15104, 56}, {-14592, 57}, {-16128, 58}, {-15616, 59},
      {-13056, 60}, {-12544, 61}, {-14080, 62}, {-13568, 63}, {-344, 64},
      {-328, 65},   {-376, 66},   {-360, 67},   {-280, 68},   {-264, 69},
      {-312, 70},   {-296, 71},   {-472, 72},   {-456, 73},   {-504, 74},
      {-488, 75},   {-408, 76},   {-392, 77},   {-440, 78},   {-424, 79},
      {-88, 80},    {-72, 81},    {-120, 82},   {-104, 83},   {-24, 84},
      {-8, 85},     {-56, 86},    {-40, 87},    {-216, 88},   {-200, 89},
      {-248, 90},   {-232, 91},   {-152, 92},   {-136, 93},   {-184, 94},
      {-168, 95},   {-1376, 96},  {-1312, 97},  {-1504, 98},  {-1440, 99},
      {-1120, 100}, {-1056, 101}, {-1248, 102}, {-1184, 103}, {-1888, 104},
      {-1824, 105}, {-2016, 106}, {-1952, 107}, {-1632, 108}, {-1568, 109},
      {-1760, 110}, {-1696, 111}, {-688, 112},  {-656, 113},  {-752, 114},
      {-720, 115},  {-560, 116},  {-528, 117},  {-624, 118},  {-592, 119},
      {-944, 120},  {-912, 121},  {-1008, 122}, {-976, 123},  {-816, 124},
      {-784, 125},  {-880, 126},  {-848, 127},  {5504, 128},  {5248, 129},
      {6016, 130},  {5760, 131},  {4480, 132},  {4224, 133},  {4992, 134},
      {4736, 135},  {7552, 136},  {7296, 137},  {8064, 138},  {7808, 139},
      {6528, 140},  {6272, 141},  {7040, 142},  {6784, 143},  {2752, 144},
      {2624, 145},  {3008, 146},  {2880, 147},  {2240, 148},  {2112, 149},
      {2496, 150},  {2368, 151},  {3776, 152},  {3648, 153},  {4032, 154},
      {3904, 155},  {3264, 156},  {3136, 157},  {3520, 158},  {3392, 159},
      {22016, 160}, {20992, 161}, {24064, 162}, {23040, 163}, {17920, 164},
      {16896, 165}, {19968, 166}, {18944, 167}, {30208, 168}, {29184, 169},
      {32256, 170}, {31232, 171}, {26112, 172}, {25088, 173}, {28160, 174},
      {27136, 175}, {11008, 176}, {10496, 177}, {12032, 178}, {11520, 179},
      {8960, 180},  {8448, 181},  {9984, 182},  {9472, 183},  {15104, 184},
      {14592, 185}, {16128, 186}, {15616, 187}, {13056, 188}, {12544, 189},
      {14080, 190}, {13568, 191}, {344, 192},   {328, 193},   {376, 194},
      {360, 195},   {280, 196},   {264, 197},   {312, 198},   {296, 199},
      {472, 200},   {456, 201},   {504, 202},   {488, 203},   {408, 204},
      {392, 205},   {440, 206},   {424, 207},   {88, 208},    {72, 209},
      {120, 210},   {104, 211},   {24, 212},    {8, 213},     {56, 214},
      {40, 215},    {216, 216},   {200, 217},   {248, 218},   {232, 219},
      {152, 220},   {136, 221},   {184, 222},   {168, 223},   {1376, 224},
      {1312, 225},  {1504, 226},  {1440, 227},  {1120, 228},  {1056, 229},
      {1248, 230},  {1184, 231},  {1888, 232},  {1824, 233},  {2016, 234},
      {1952, 235},  {1632, 236},  {1568, 237},  {1760, 238},  {1696, 239},
      {688, 240},   {656, 241},   {752, 242},   {720, 243},   {560, 244},
      {528, 245},   {624, 246},   {592, 247},   {944, 248},   {912, 249},
      {1008, 250},  {976, 251},   {816, 252},   {784, 253},   {880, 254},
      {848, 255},
  };
  for (i = 0; i < ARRAYLEN(V); ++i) {
    ASSERT_EQ(V[i][0], unalaw(V[i][1]));
  }
}

BENCH(alaw, bench) {
  char *p = gc(malloc(kHyperionSize));
  EZBENCH2("alaw -32k", donothing, alaw(-32768));
  EZBENCH2("alaw 32k", donothing, alaw(32767));
  EZBENCH2("unalaw 0", donothing, unalaw(0));
  EZBENCH2("unalaw 255", donothing, unalaw(255));
}