Replace hbd adst4 with lbd adst4

0.05% drop in performance for 10 bit
0.03% drop in performance for 12 bit

Updated relevant tests:
- Use the fadst4 function from VP9 as the reference.
- Update some max/avg error thresholds

Change-Id: Ic8c5b591eea3309427d2bb42828d44e640f718a1
diff --git a/av1/common/av1_inv_txfm1d.c b/av1/common/av1_inv_txfm1d.c
index f19a39a..05d090f 100644
--- a/av1/common/av1_inv_txfm1d.c
+++ b/av1/common/av1_inv_txfm1d.c
@@ -735,67 +735,42 @@
 
 void av1_iadst4_new(const int32_t *input, int32_t *output,
                     const int8_t *cos_bit, const int8_t *stage_range) {
-  const int32_t size = 4;
-  const int32_t *cospi;
+  (void)cos_bit;
+  int bd = stage_range[0];
+  int64_t s0, s1, s2, s3, s4, s5, s6, s7;
 
-  int32_t stage = 0;
-  int32_t *bf0, *bf1;
-  int32_t step[4];
+  int32_t x0 = input[0];
+  int32_t x1 = input[1];
+  int32_t x2 = input[2];
+  int32_t x3 = input[3];
 
-  // stage 0;
-  range_check(stage, input, input, size, stage_range[stage]);
+  if (!(x0 | x1 | x2 | x3)) {
+    output[0] = output[1] = output[2] = output[3] = 0;
+    return;
+  }
 
-  // stage 1;
-  stage++;
-  assert(output != input);
-  bf1 = output;
-  bf1[0] = input[0];
-  bf1[1] = -input[3];
-  bf1[2] = -input[1];
-  bf1[3] = input[2];
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  s0 = sinpi_1_9 * x0;
+  s1 = sinpi_2_9 * x0;
+  s2 = sinpi_3_9 * x1;
+  s3 = sinpi_4_9 * x2;
+  s4 = sinpi_1_9 * x2;
+  s5 = sinpi_2_9 * x3;
+  s6 = sinpi_4_9 * x3;
+  s7 = HIGHBD_WRAPLOW(x0 - x2 + x3, bd);
 
-  // stage 2
-  stage++;
-  cospi = cospi_arr(cos_bit[stage]);
-  bf0 = output;
-  bf1 = step;
-  bf1[0] = bf0[0];
-  bf1[1] = bf0[1];
-  bf1[2] = half_btf(cospi[32], bf0[2], cospi[32], bf0[3], cos_bit[stage]);
-  bf1[3] = half_btf(cospi[32], bf0[2], -cospi[32], bf0[3], cos_bit[stage]);
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  s0 = s0 + s3 + s5;
+  s1 = s1 - s4 - s6;
+  s3 = s2;
+  s2 = sinpi_3_9 * s7;
 
-  // stage 3
-  stage++;
-  bf0 = step;
-  bf1 = output;
-  bf1[0] = bf0[0] + bf0[2];
-  bf1[1] = bf0[1] + bf0[3];
-  bf1[2] = bf0[0] - bf0[2];
-  bf1[3] = bf0[1] - bf0[3];
-  range_check(stage, input, bf1, size, stage_range[stage]);
-
-  // stage 4
-  stage++;
-  cospi = cospi_arr(cos_bit[stage]);
-  bf0 = output;
-  bf1 = step;
-  bf1[0] = half_btf(cospi[8], bf0[0], cospi[56], bf0[1], cos_bit[stage]);
-  bf1[1] = half_btf(cospi[56], bf0[0], -cospi[8], bf0[1], cos_bit[stage]);
-  bf1[2] = half_btf(cospi[40], bf0[2], cospi[24], bf0[3], cos_bit[stage]);
-  bf1[3] = half_btf(cospi[24], bf0[2], -cospi[40], bf0[3], cos_bit[stage]);
-  range_check(stage, input, bf1, size, stage_range[stage]);
-
-  // stage 5
-  stage++;
-  bf0 = step;
-  bf1 = output;
-  bf1[0] = bf0[1];
-  bf1[1] = bf0[2];
-  bf1[2] = bf0[3];
-  bf1[3] = bf0[0];
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  // 1-D transform scaling factor is sqrt(2).
+  // The overall dynamic range is 14b (input) + 14b (multiplication scaling)
+  // + 1b (addition) = 29b.
+  // Hence the output bit depth is 15b.
+  output[0] = HIGHBD_WRAPLOW(dct_const_round_shift(s0 + s3), bd);
+  output[1] = HIGHBD_WRAPLOW(dct_const_round_shift(s1 + s3), bd);
+  output[2] = HIGHBD_WRAPLOW(dct_const_round_shift(s2), bd);
+  output[3] = HIGHBD_WRAPLOW(dct_const_round_shift(s0 + s1 - s3), bd);
 }
 
 void av1_iadst8_new(const int32_t *input, int32_t *output,
diff --git a/av1/common/x86/highbd_inv_txfm_sse4.c b/av1/common/x86/highbd_inv_txfm_sse4.c
index b21c7db..075b9fc 100644
--- a/av1/common/x86/highbd_inv_txfm_sse4.c
+++ b/av1/common/x86/highbd_inv_txfm_sse4.c
@@ -72,77 +72,67 @@
 }
 
 static void iadst4x4_sse4_1(__m128i *in, int bit) {
-  const int32_t *cospi = cospi_arr(bit);
-  const __m128i cospi32 = _mm_set1_epi32(cospi[32]);
-  const __m128i cospi8 = _mm_set1_epi32(cospi[8]);
-  const __m128i cospim8 = _mm_set1_epi32(-cospi[8]);
-  const __m128i cospi40 = _mm_set1_epi32(cospi[40]);
-  const __m128i cospim40 = _mm_set1_epi32(-cospi[40]);
-  const __m128i cospi24 = _mm_set1_epi32(cospi[24]);
-  const __m128i cospi56 = _mm_set1_epi32(cospi[56]);
+  bit = 14;
   const __m128i rnding = _mm_set1_epi32(1 << (bit - 1));
-  const __m128i zero = _mm_setzero_si128();
+  const __m128i sinpi1 = _mm_set1_epi32(sinpi_1_9);
+  const __m128i sinpi2 = _mm_set1_epi32(sinpi_2_9);
+  const __m128i sinpi3 = _mm_set1_epi32(sinpi_3_9);
+  const __m128i sinpi4 = _mm_set1_epi32(sinpi_4_9);
+  __m128i t;
+  __m128i s0, s1, s2, s3, s4, s5, s6, s7;
+  __m128i x0, x1, x2, x3;
   __m128i u0, u1, u2, u3;
-  __m128i v0, v1, v2, v3, x, y;
+  __m128i v0, v1, v2, v3;
 
   v0 = _mm_unpacklo_epi32(in[0], in[1]);
   v1 = _mm_unpackhi_epi32(in[0], in[1]);
   v2 = _mm_unpacklo_epi32(in[2], in[3]);
   v3 = _mm_unpackhi_epi32(in[2], in[3]);
 
-  u0 = _mm_unpacklo_epi64(v0, v2);
-  u1 = _mm_unpackhi_epi64(v0, v2);
-  u2 = _mm_unpacklo_epi64(v1, v3);
-  u3 = _mm_unpackhi_epi64(v1, v3);
+  x0 = _mm_unpacklo_epi64(v0, v2);
+  x1 = _mm_unpackhi_epi64(v0, v2);
+  x2 = _mm_unpacklo_epi64(v1, v3);
+  x3 = _mm_unpackhi_epi64(v1, v3);
 
-  // stage 0
-  // stage 1
-  u1 = _mm_sub_epi32(zero, u1);
-  u3 = _mm_sub_epi32(zero, u3);
+  s0 = _mm_mullo_epi32(x0, sinpi1);
+  s1 = _mm_mullo_epi32(x0, sinpi2);
+  s2 = _mm_mullo_epi32(x1, sinpi3);
+  s3 = _mm_mullo_epi32(x2, sinpi4);
+  s4 = _mm_mullo_epi32(x2, sinpi1);
+  s5 = _mm_mullo_epi32(x3, sinpi2);
+  s6 = _mm_mullo_epi32(x3, sinpi4);
+  t = _mm_sub_epi32(x0, x2);
+  s7 = _mm_add_epi32(t, x3);
 
-  // stage 2
-  v0 = u0;
-  v1 = u3;
-  x = _mm_mullo_epi32(u1, cospi32);
-  y = _mm_mullo_epi32(u2, cospi32);
-  v2 = _mm_add_epi32(x, y);
-  v2 = _mm_add_epi32(v2, rnding);
-  v2 = _mm_srai_epi32(v2, bit);
+  t = _mm_add_epi32(s0, s3);
+  s0 = _mm_add_epi32(t, s5);
+  t = _mm_sub_epi32(s1, s4);
+  s1 = _mm_sub_epi32(t, s6);
+  s3 = s2;
+  s2 = _mm_mullo_epi32(s7, sinpi3);
 
-  v3 = _mm_sub_epi32(x, y);
-  v3 = _mm_add_epi32(v3, rnding);
-  v3 = _mm_srai_epi32(v3, bit);
+  u0 = _mm_add_epi32(s0, s3);
+  u1 = _mm_add_epi32(s1, s3);
+  u2 = s2;
+  t = _mm_add_epi32(s0, s1);
+  u3 = _mm_sub_epi32(t, s3);
 
-  // stage 3
-  u0 = _mm_add_epi32(v0, v2);
-  u1 = _mm_add_epi32(v1, v3);
-  u2 = _mm_sub_epi32(v0, v2);
-  u3 = _mm_sub_epi32(v1, v3);
+  u0 = _mm_add_epi32(u0, rnding);
+  u0 = _mm_srai_epi32(u0, bit);
 
-  // stage 4
-  x = _mm_mullo_epi32(u0, cospi8);
-  y = _mm_mullo_epi32(u1, cospi56);
-  in[3] = _mm_add_epi32(x, y);
-  in[3] = _mm_add_epi32(in[3], rnding);
-  in[3] = _mm_srai_epi32(in[3], bit);
+  u1 = _mm_add_epi32(u1, rnding);
+  u1 = _mm_srai_epi32(u1, bit);
 
-  x = _mm_mullo_epi32(u0, cospi56);
-  y = _mm_mullo_epi32(u1, cospim8);
-  in[0] = _mm_add_epi32(x, y);
-  in[0] = _mm_add_epi32(in[0], rnding);
-  in[0] = _mm_srai_epi32(in[0], bit);
+  u2 = _mm_add_epi32(u2, rnding);
+  u2 = _mm_srai_epi32(u2, bit);
 
-  x = _mm_mullo_epi32(u2, cospi40);
-  y = _mm_mullo_epi32(u3, cospi24);
-  in[1] = _mm_add_epi32(x, y);
-  in[1] = _mm_add_epi32(in[1], rnding);
-  in[1] = _mm_srai_epi32(in[1], bit);
+  u3 = _mm_add_epi32(u3, rnding);
+  u3 = _mm_srai_epi32(u3, bit);
 
-  x = _mm_mullo_epi32(u2, cospi24);
-  y = _mm_mullo_epi32(u3, cospim40);
-  in[2] = _mm_add_epi32(x, y);
-  in[2] = _mm_add_epi32(in[2], rnding);
-  in[2] = _mm_srai_epi32(in[2], bit);
+  in[0] = u0;
+  in[1] = u1;
+  in[2] = u2;
+  in[3] = u3;
 }
 
 static INLINE void round_shift_4x4(__m128i *in, int shift) {
diff --git a/av1/encoder/av1_fwd_txfm1d.c b/av1/encoder/av1_fwd_txfm1d.c
index 2e66dac..0e8cb75 100644
--- a/av1/encoder/av1_fwd_txfm1d.c
+++ b/av1/encoder/av1_fwd_txfm1d.c
@@ -692,66 +692,45 @@
 
 void av1_fadst4_new(const int32_t *input, int32_t *output,
                     const int8_t *cos_bit, const int8_t *stage_range) {
-  const int32_t size = 4;
-  const int32_t *cospi;
+  (void)cos_bit;
+  (void)stage_range;
+  int64_t x0, x1, x2, x3;
+  int64_t s0, s1, s2, s3, s4, s5, s6, s7;
 
-  int32_t stage = 0;
-  int32_t *bf0, *bf1;
-  int32_t step[4];
+  x0 = input[0];
+  x1 = input[1];
+  x2 = input[2];
+  x3 = input[3];
 
-  // stage 0;
-  range_check(stage, input, input, size, stage_range[stage]);
+  if (!(x0 | x1 | x2 | x3)) {
+    output[0] = output[1] = output[2] = output[3] = 0;
+    return;
+  }
 
-  // stage 1;
-  stage++;
-  bf1 = output;
-  bf1[0] = input[3];
-  bf1[1] = input[0];
-  bf1[2] = input[1];
-  bf1[3] = input[2];
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  s0 = sinpi_1_9 * x0;
+  s1 = sinpi_4_9 * x0;
+  s2 = sinpi_2_9 * x1;
+  s3 = sinpi_1_9 * x1;
+  s4 = sinpi_3_9 * x2;
+  s5 = sinpi_4_9 * x3;
+  s6 = sinpi_2_9 * x3;
+  s7 = x0 + x1 - x3;
 
-  // stage 2
-  stage++;
-  cospi = cospi_arr(cos_bit[stage]);
-  bf0 = output;
-  bf1 = step;
-  bf1[0] = half_btf(cospi[8], bf0[0], cospi[56], bf0[1], cos_bit[stage]);
-  bf1[1] = half_btf(-cospi[8], bf0[1], cospi[56], bf0[0], cos_bit[stage]);
-  bf1[2] = half_btf(cospi[40], bf0[2], cospi[24], bf0[3], cos_bit[stage]);
-  bf1[3] = half_btf(-cospi[40], bf0[3], cospi[24], bf0[2], cos_bit[stage]);
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  x0 = s0 + s2 + s5;
+  x1 = sinpi_3_9 * s7;
+  x2 = s1 - s3 + s6;
+  x3 = s4;
 
-  // stage 3
-  stage++;
-  bf0 = step;
-  bf1 = output;
-  bf1[0] = bf0[0] + bf0[2];
-  bf1[1] = bf0[1] + bf0[3];
-  bf1[2] = -bf0[2] + bf0[0];
-  bf1[3] = -bf0[3] + bf0[1];
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  s0 = x0 + x3;
+  s1 = x1;
+  s2 = x2 - x3;
+  s3 = x2 - x0 + x3;
 
-  // stage 4
-  stage++;
-  cospi = cospi_arr(cos_bit[stage]);
-  bf0 = output;
-  bf1 = step;
-  bf1[0] = bf0[0];
-  bf1[1] = bf0[1];
-  bf1[2] = half_btf(cospi[32], bf0[2], cospi[32], bf0[3], cos_bit[stage]);
-  bf1[3] = half_btf(-cospi[32], bf0[3], cospi[32], bf0[2], cos_bit[stage]);
-  range_check(stage, input, bf1, size, stage_range[stage]);
-
-  // stage 5
-  stage++;
-  bf0 = step;
-  bf1 = output;
-  bf1[0] = bf0[0];
-  bf1[1] = -bf0[2];
-  bf1[2] = bf0[3];
-  bf1[3] = -bf0[1];
-  range_check(stage, input, bf1, size, stage_range[stage]);
+  // 1-D transform scaling factor is sqrt(2).
+  output[0] = (int32_t)fdct_round_shift(s0);
+  output[1] = (int32_t)fdct_round_shift(s1);
+  output[2] = (int32_t)fdct_round_shift(s2);
+  output[3] = (int32_t)fdct_round_shift(s3);
 }
 
 void av1_fadst8_new(const int32_t *input, int32_t *output,
diff --git a/av1/encoder/x86/highbd_fwd_txfm_sse4.c b/av1/encoder/x86/highbd_fwd_txfm_sse4.c
index d772761..2b788ac 100644
--- a/av1/encoder/x86/highbd_fwd_txfm_sse4.c
+++ b/av1/encoder/x86/highbd_fwd_txfm_sse4.c
@@ -121,72 +121,57 @@
 }
 
 static void fadst4x4_sse4_1(__m128i *in, int bit) {
-  const int32_t *cospi = cospi_arr(bit);
-  const __m128i cospi8 = _mm_set1_epi32(cospi[8]);
-  const __m128i cospi56 = _mm_set1_epi32(cospi[56]);
-  const __m128i cospi40 = _mm_set1_epi32(cospi[40]);
-  const __m128i cospi24 = _mm_set1_epi32(cospi[24]);
-  const __m128i cospi32 = _mm_set1_epi32(cospi[32]);
+  bit = 14;
   const __m128i rnding = _mm_set1_epi32(1 << (bit - 1));
-  const __m128i kZero = _mm_setzero_si128();
-  __m128i s0, s1, s2, s3;
+  const __m128i sinpi1 = _mm_set1_epi32(sinpi_1_9);
+  const __m128i sinpi2 = _mm_set1_epi32(sinpi_2_9);
+  const __m128i sinpi3 = _mm_set1_epi32(sinpi_3_9);
+  const __m128i sinpi4 = _mm_set1_epi32(sinpi_4_9);
+  __m128i t;
+  __m128i s0, s1, s2, s3, s4, s5, s6, s7;
+  __m128i x0, x1, x2, x3;
   __m128i u0, u1, u2, u3;
   __m128i v0, v1, v2, v3;
 
-  // stage 0
-  // stage 1
-  // stage 2
-  u0 = _mm_mullo_epi32(in[3], cospi8);
-  u1 = _mm_mullo_epi32(in[0], cospi56);
-  u2 = _mm_add_epi32(u0, u1);
-  s0 = _mm_add_epi32(u2, rnding);
-  s0 = _mm_srai_epi32(s0, bit);
+  s0 = _mm_mullo_epi32(in[0], sinpi1);
+  s1 = _mm_mullo_epi32(in[0], sinpi4);
+  s2 = _mm_mullo_epi32(in[1], sinpi2);
+  s3 = _mm_mullo_epi32(in[1], sinpi1);
+  s4 = _mm_mullo_epi32(in[2], sinpi3);
+  s5 = _mm_mullo_epi32(in[3], sinpi4);
+  s6 = _mm_mullo_epi32(in[3], sinpi2);
+  t = _mm_add_epi32(in[0], in[1]);
+  s7 = _mm_sub_epi32(t, in[3]);
 
-  v0 = _mm_mullo_epi32(in[3], cospi56);
-  v1 = _mm_mullo_epi32(in[0], cospi8);
-  v2 = _mm_sub_epi32(v0, v1);
-  s1 = _mm_add_epi32(v2, rnding);
-  s1 = _mm_srai_epi32(s1, bit);
+  t = _mm_add_epi32(s0, s2);
+  x0 = _mm_add_epi32(t, s5);
+  x1 = _mm_mullo_epi32(s7, sinpi3);
+  t = _mm_sub_epi32(s1, s3);
+  x2 = _mm_add_epi32(t, s6);
+  x3 = s4;
 
-  u0 = _mm_mullo_epi32(in[1], cospi40);
-  u1 = _mm_mullo_epi32(in[2], cospi24);
-  u2 = _mm_add_epi32(u0, u1);
-  s2 = _mm_add_epi32(u2, rnding);
-  s2 = _mm_srai_epi32(s2, bit);
+  s0 = _mm_add_epi32(x0, x3);
+  s1 = x1;
+  s2 = _mm_sub_epi32(x2, x3);
+  t = _mm_sub_epi32(x2, x0);
+  s3 = _mm_add_epi32(t, x3);
 
-  v0 = _mm_mullo_epi32(in[1], cospi24);
-  v1 = _mm_mullo_epi32(in[2], cospi40);
-  v2 = _mm_sub_epi32(v0, v1);
-  s3 = _mm_add_epi32(v2, rnding);
-  s3 = _mm_srai_epi32(s3, bit);
+  u0 = _mm_add_epi32(s0, rnding);
+  u0 = _mm_srai_epi32(u0, bit);
 
-  // stage 3
-  u0 = _mm_add_epi32(s0, s2);
-  u2 = _mm_sub_epi32(s0, s2);
-  u1 = _mm_add_epi32(s1, s3);
-  u3 = _mm_sub_epi32(s1, s3);
+  u1 = _mm_add_epi32(s1, rnding);
+  u1 = _mm_srai_epi32(u1, bit);
 
-  // stage 4
-  v0 = _mm_mullo_epi32(u2, cospi32);
-  v1 = _mm_mullo_epi32(u3, cospi32);
-  v2 = _mm_add_epi32(v0, v1);
-  s2 = _mm_add_epi32(v2, rnding);
-  u2 = _mm_srai_epi32(s2, bit);
+  u2 = _mm_add_epi32(s2, rnding);
+  u2 = _mm_srai_epi32(u2, bit);
 
-  v2 = _mm_sub_epi32(v0, v1);
-  s3 = _mm_add_epi32(v2, rnding);
-  u3 = _mm_srai_epi32(s3, bit);
+  u3 = _mm_add_epi32(s3, rnding);
+  u3 = _mm_srai_epi32(u3, bit);
 
-  // u0, u1, u2, u3
-  u2 = _mm_sub_epi32(kZero, u2);
-  u1 = _mm_sub_epi32(kZero, u1);
-
-  // u0, u2, u3, u1
-  // Transpose 4x4 32-bit
-  v0 = _mm_unpacklo_epi32(u0, u2);
-  v1 = _mm_unpackhi_epi32(u0, u2);
-  v2 = _mm_unpacklo_epi32(u3, u1);
-  v3 = _mm_unpackhi_epi32(u3, u1);
+  v0 = _mm_unpacklo_epi32(u0, u1);
+  v1 = _mm_unpackhi_epi32(u0, u1);
+  v2 = _mm_unpacklo_epi32(u2, u3);
+  v3 = _mm_unpackhi_epi32(u2, u3);
 
   in[0] = _mm_unpacklo_epi64(v0, v2);
   in[1] = _mm_unpackhi_epi64(v0, v2);
diff --git a/test/av1_fwd_txfm1d_test.cc b/test/av1_fwd_txfm1d_test.cc
index e6bab68..ecfd7c6 100644
--- a/test/av1_fwd_txfm1d_test.cc
+++ b/test/av1_fwd_txfm1d_test.cc
@@ -86,9 +86,10 @@
           reference_hybrid_1d(ref_input, ref_output, txfm_size, txfm_type);
 
           for (int ni = 0; ni < txfm_size; ++ni) {
-            EXPECT_LE(
+            ASSERT_LE(
                 abs(output[ni] - static_cast<int32_t>(round(ref_output[ni]))),
-                max_error);
+                max_error)
+                << "tx size = " << txfm_size << ", tx type = " << txfm_type;
           }
         }
       }
diff --git a/test/av1_fwd_txfm2d_test.cc b/test/av1_fwd_txfm2d_test.cc
index b25e981..be353ef 100644
--- a/test/av1_fwd_txfm2d_test.cc
+++ b/test/av1_fwd_txfm2d_test.cc
@@ -139,20 +139,20 @@
   vector<AV1FwdTxfm2dParam> param_list;
   for (int t = 0; t <= FLIPADST_ADST; ++t) {
     const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
-    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X4, 2, 0.2));
+    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X4, 2, 0.5));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X8, 5, 0.6));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X16, 11, 1.5));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X32, 70, 7));
 
-    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X8, 2.5, 0.4));
-    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X4, 2.5, 0.4));
+    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X8, 2.9, 0.55));
+    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X4, 3.2, 0.56));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X16, 6.5, 1));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X8, 6.5, 1));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X32, 46, 7));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X16, 30, 7));
 
-    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X16, 5, 0.6));
-    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X4, 5, 0.6));
+    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X16, 5, 0.7));
+    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X4, 5.5, 0.9));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X32, 14, 2.1));
     param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X8, 11, 1.6));
 
diff --git a/test/av1_txfm_test.cc b/test/av1_txfm_test.cc
index 2e937cb..b7710d2 100644
--- a/test/av1_txfm_test.cc
+++ b/test/av1_txfm_test.cc
@@ -90,7 +90,62 @@
   }
 }
 
+// TODO(any): Copied from dct.c. Should be replaced by a proper reference
+// function that takes 'double' input & output.
+static void fadst4(const tran_low_t *input, tran_low_t *output) {
+  tran_high_t x0, x1, x2, x3;
+  tran_high_t s0, s1, s2, s3, s4, s5, s6, s7;
+
+  x0 = input[0];
+  x1 = input[1];
+  x2 = input[2];
+  x3 = input[3];
+
+  if (!(x0 | x1 | x2 | x3)) {
+    output[0] = output[1] = output[2] = output[3] = 0;
+    return;
+  }
+
+  s0 = sinpi_1_9 * x0;
+  s1 = sinpi_4_9 * x0;
+  s2 = sinpi_2_9 * x1;
+  s3 = sinpi_1_9 * x1;
+  s4 = sinpi_3_9 * x2;
+  s5 = sinpi_4_9 * x3;
+  s6 = sinpi_2_9 * x3;
+  s7 = x0 + x1 - x3;
+
+  x0 = s0 + s2 + s5;
+  x1 = sinpi_3_9 * s7;
+  x2 = s1 - s3 + s6;
+  x3 = s4;
+
+  s0 = x0 + x3;
+  s1 = x1;
+  s2 = x2 - x3;
+  s3 = x2 - x0 + x3;
+
+  // 1-D transform scaling factor is sqrt(2).
+  output[0] = (tran_low_t)fdct_round_shift(s0);
+  output[1] = (tran_low_t)fdct_round_shift(s1);
+  output[2] = (tran_low_t)fdct_round_shift(s2);
+  output[3] = (tran_low_t)fdct_round_shift(s3);
+}
+
 void reference_adst_1d(const double *in, double *out, int size) {
+  if (size == 4) {  // Special case.
+    tran_low_t int_input[4];
+    for (int i = 0; i < 4; ++i) {
+      int_input[i] = static_cast<tran_low_t>(round(in[i]));
+    }
+    tran_low_t int_output[4];
+    fadst4(int_input, int_output);
+    for (int i = 0; i < 4; ++i) {
+      out[i] = int_output[i];
+    }
+    return;
+  }
+
   for (int k = 0; k < size; ++k) {
     out[k] = 0;
     for (int n = 0; n < size; ++n) {