| // Copyright 2023 The Wuffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| //go:build ignore |
| // +build ignore |
| |
| package main |
| |
| // print-jpeg-idct-code.go prints the "func jpeg.decoder.decode_idct" code. |
| // |
| // Usage: go run print-jpeg-idct-code.go |
| |
| import ( |
| "fmt" |
| "os" |
| "strings" |
| ) |
| |
| func main() { |
| if err := main1(); err != nil { |
| os.Stderr.WriteString(err.Error() + "\n") |
| os.Exit(1) |
| } |
| } |
| |
| func main1() error { |
| fmt.Printf("// -------- BEGIN generated by script/print-jpeg-idct-code.go\n") |
| fmt.Println() |
| |
| fmt.Printf("// p0_298631336 = 0x%04X = %5d\n", round(p0_298631336), round(p0_298631336)) |
| fmt.Printf("// p0_390180644 = 0x%04X = %5d\n", round(p0_390180644), round(p0_390180644)) |
| fmt.Printf("// p0_541196100 = 0x%04X = %5d\n", round(p0_541196100), round(p0_541196100)) |
| fmt.Printf("// p0_765366865 = 0x%04X = %5d\n", round(p0_765366865), round(p0_765366865)) |
| fmt.Printf("// p0_899976223 = 0x%04X = %5d\n", round(p0_899976223), round(p0_899976223)) |
| fmt.Printf("// p1_175875602 = 0x%04X = %5d\n", round(p1_175875602), round(p1_175875602)) |
| fmt.Printf("// p1_501321110 = 0x%04X = %5d\n", round(p1_501321110), round(p1_501321110)) |
| fmt.Printf("// p1_847759065 = 0x%04X = %5d\n", round(p1_847759065), round(p1_847759065)) |
| fmt.Printf("// p1_961570560 = 0x%04X = %5d\n", round(p1_961570560), round(p1_961570560)) |
| fmt.Printf("// p2_053119869 = 0x%04X = %5d\n", round(p2_053119869), round(p2_053119869)) |
| fmt.Printf("// p2_562915447 = 0x%04X = %5d\n", round(p2_562915447), round(p2_562915447)) |
| fmt.Printf("// p3_072711026 = 0x%04X = %5d\n", round(p3_072711026), round(p3_072711026)) |
| fmt.Printf("//\n") |
| fmt.Printf("// m0_390180644 = 0x%08X = %10d\n", round(m0_390180644), round(m0_390180644)) |
| fmt.Printf("// m0_899976223 = 0x%08X = %10d\n", round(m0_899976223), round(m0_899976223)) |
| fmt.Printf("// m1_961570560 = 0x%08X = %10d\n", round(m1_961570560), round(m1_961570560)) |
| fmt.Printf("// m2_562915447 = 0x%08X = %10d\n", round(m2_562915447), round(m2_562915447)) |
| fmt.Println() |
| |
| for x := 0; x < 8; x++ { |
| fmt.Println(strings.TrimSpace(replace(pass0, map[string]string{ |
| "$colX$": fmt.Sprint(x), |
| "$row0colX$": fmt.Sprintf("0x%02X", (8*0)|x), |
| "$row1colX$": fmt.Sprintf("0x%02X", (8*1)|x), |
| "$row2colX$": fmt.Sprintf("0x%02X", (8*2)|x), |
| "$row3colX$": fmt.Sprintf("0x%02X", (8*3)|x), |
| "$row4colX$": fmt.Sprintf("0x%02X", (8*4)|x), |
| "$row5colX$": fmt.Sprintf("0x%02X", (8*5)|x), |
| "$row6colX$": fmt.Sprintf("0x%02X", (8*6)|x), |
| "$row7colX$": fmt.Sprintf("0x%02X", (8*7)|x), |
| "$p0_298631336$": fmt.Sprintf("0x%04X", round(p0_298631336)), |
| "$p0_541196100$": fmt.Sprintf("0x%04X", round(p0_541196100)), |
| "$p0_765366865$": fmt.Sprintf("0x%04X", round(p0_765366865)), |
| "$p1_175875602$": fmt.Sprintf("0x%04X", round(p1_175875602)), |
| "$p1_501321110$": fmt.Sprintf("0x%04X", round(p1_501321110)), |
| "$p1_847759065$": fmt.Sprintf("0x%04X", round(p1_847759065)), |
| "$p2_053119869$": fmt.Sprintf("0x%04X", round(p2_053119869)), |
| "$p3_072711026$": fmt.Sprintf("0x%04X", round(p3_072711026)), |
| "$m0_390180644$": fmt.Sprintf("0x%08X", round(m0_390180644)), |
| "$m0_899976223$": fmt.Sprintf("0x%08X", round(m0_899976223)), |
| "$m1_961570560$": fmt.Sprintf("0x%08X", round(m1_961570560)), |
| "$m2_562915447$": fmt.Sprintf("0x%08X", round(m2_562915447)), |
| }))) |
| fmt.Println() |
| } |
| |
| for y := 0; y < 8; y++ { |
| fmt.Println(strings.TrimSpace(replace(pass1, map[string]string{ |
| "$rowY$": fmt.Sprint(y), |
| "$rowYcol0$": fmt.Sprintf("0x%02X", (8*y)|0), |
| "$rowYcol1$": fmt.Sprintf("0x%02X", (8*y)|1), |
| "$rowYcol2$": fmt.Sprintf("0x%02X", (8*y)|2), |
| "$rowYcol3$": fmt.Sprintf("0x%02X", (8*y)|3), |
| "$rowYcol4$": fmt.Sprintf("0x%02X", (8*y)|4), |
| "$rowYcol5$": fmt.Sprintf("0x%02X", (8*y)|5), |
| "$rowYcol6$": fmt.Sprintf("0x%02X", (8*y)|6), |
| "$rowYcol7$": fmt.Sprintf("0x%02X", (8*y)|7), |
| "$p0_298631336$": fmt.Sprintf("0x%04X", round(p0_298631336)), |
| "$p0_541196100$": fmt.Sprintf("0x%04X", round(p0_541196100)), |
| "$p0_765366865$": fmt.Sprintf("0x%04X", round(p0_765366865)), |
| "$p1_175875602$": fmt.Sprintf("0x%04X", round(p1_175875602)), |
| "$p1_501321110$": fmt.Sprintf("0x%04X", round(p1_501321110)), |
| "$p1_847759065$": fmt.Sprintf("0x%04X", round(p1_847759065)), |
| "$p2_053119869$": fmt.Sprintf("0x%04X", round(p2_053119869)), |
| "$p3_072711026$": fmt.Sprintf("0x%04X", round(p3_072711026)), |
| "$m0_390180644$": fmt.Sprintf("0x%08X", round(m0_390180644)), |
| "$m0_899976223$": fmt.Sprintf("0x%08X", round(m0_899976223)), |
| "$m1_961570560$": fmt.Sprintf("0x%08X", round(m1_961570560)), |
| "$m2_562915447$": fmt.Sprintf("0x%08X", round(m2_562915447)), |
| "$bounds_check$": boundsCheck(y == 7), |
| "$advance$": advance(y == 7), |
| }))) |
| fmt.Println() |
| } |
| |
| fmt.Printf("// -------- END generated by script/print-jpeg-idct-code.go\n") |
| return nil |
| } |
| |
| func replace(s string, m map[string]string) string { |
| for k, v := range m { |
| s = strings.ReplaceAll(s, k, v) |
| } |
| return s |
| } |
| |
| func round(x float64) uint32 { |
| return uint32(0.5 + (x * (1 << 13))) |
| } |
| |
| func boundsCheck(final bool) string { |
| if final { |
| return "" + |
| "if 8 > args.dst_buffer.length() {\n" + |
| " return nothing\n" + |
| "}" |
| } |
| return "" + |
| "if args.dst_stride > args.dst_buffer.length() {\n" + |
| " return nothing\n" + |
| "}\n" + |
| `assert 8 <= args.dst_buffer.length() via "a <= b: a <= c; c <= b"(c: args.dst_stride)` |
| } |
| |
| func advance(final bool) string { |
| if final { |
| return "" |
| } |
| return "args.dst_buffer = args.dst_buffer[args.dst_stride ..]" |
| } |
| |
| const ( |
| sqrt2 = 1.4142135623730950488016887242096980785696718753769480731766797379 |
| |
| // cosNpi16 ≈ cos(N * (pi / 16)). |
| cos1pi16 = 0.9807852804032304491261822361342390369739337308933360950029160885 |
| cos2pi16 = 0.9238795325112867561281831893967882868224166258636424861150977312 |
| cos3pi16 = 0.8314696123025452370787883776179057567385608119872499634461245902 |
| cos5pi16 = 0.5555702330196022247428308139485328743749371907548040459241535282 |
| cos6pi16 = 0.3826834323650897717284599840303988667613445624856270414338006356 |
| cos7pi16 = 0.1950903220161282678482848684770222409276916177519548077545020894 |
| ) |
| |
| const ( |
| p0_541196100 = sqrt2 * (+cos6pi16) |
| p1_175875602 = sqrt2 * (+cos3pi16) |
| |
| p0_765366865 = sqrt2 * (+cos2pi16 - cos6pi16) |
| p1_847759065 = sqrt2 * (+cos2pi16 + cos6pi16) |
| |
| p0_390180644 = sqrt2 * (+cos3pi16 - cos5pi16) |
| p0_899976223 = sqrt2 * (+cos3pi16 - cos7pi16) |
| p1_961570560 = sqrt2 * (+cos3pi16 + cos5pi16) |
| p2_562915447 = sqrt2 * (+cos3pi16 + cos1pi16) |
| |
| p0_298631336 = sqrt2 * (-cos1pi16 + cos3pi16 + cos5pi16 - cos7pi16) |
| p1_501321110 = sqrt2 * (+cos1pi16 + cos3pi16 - cos5pi16 - cos7pi16) |
| p2_053119869 = sqrt2 * (+cos1pi16 + cos3pi16 - cos5pi16 + cos7pi16) |
| p3_072711026 = sqrt2 * (+cos1pi16 + cos3pi16 + cos5pi16 - cos7pi16) |
| |
| m0_390180644 = (1 << (32 - 13)) - p0_390180644 |
| m0_899976223 = (1 << (32 - 13)) - p0_899976223 |
| m1_961570560 = (1 << (32 - 13)) - p1_961570560 |
| m2_562915447 = (1 << (32 - 13)) - p2_562915447 |
| ) |
| |
| const pass0 = `// ==== First pass, column $colX$. |
| |
| // Even rows. |
| |
| bq2 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row2colX$]) ~mod* (this.quant_tables[args.q][$row2colX$] as base.u32) |
| bq6 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row6colX$]) ~mod* (this.quant_tables[args.q][$row6colX$] as base.u32) |
| |
| ca = (bq2 ~mod+ bq6) ~mod* $p0_541196100$ |
| |
| cb2 = ca ~mod+ (bq2 ~mod* $p0_765366865$) |
| cb6 = ca ~mod- (bq6 ~mod* $p1_847759065$) |
| |
| bq0 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row0colX$]) ~mod* (this.quant_tables[args.q][$row0colX$] as base.u32) |
| bq4 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row4colX$]) ~mod* (this.quant_tables[args.q][$row4colX$] as base.u32) |
| |
| ccp = (bq0 ~mod+ bq4) ~mod<< 13 |
| ccm = (bq0 ~mod- bq4) ~mod<< 13 |
| |
| cd0 = ccp ~mod+ cb2 |
| cd1 = ccm ~mod+ cb6 |
| cd2 = ccm ~mod- cb6 |
| cd3 = ccp ~mod- cb2 |
| |
| // Odd rows. |
| |
| bq1 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row1colX$]) ~mod* (this.quant_tables[args.q][$row1colX$] as base.u32) |
| bq3 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row3colX$]) ~mod* (this.quant_tables[args.q][$row3colX$] as base.u32) |
| bq5 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row5colX$]) ~mod* (this.quant_tables[args.q][$row5colX$] as base.u32) |
| bq7 = this.util.sign_extend_convert_u16_u32(a: this.mcu_blocks[args.b][$row7colX$]) ~mod* (this.quant_tables[args.q][$row7colX$] as base.u32) |
| |
| ci51 = bq5 ~mod+ bq1 |
| ci53 = bq5 ~mod+ bq3 |
| ci71 = bq7 ~mod+ bq1 |
| ci73 = bq7 ~mod+ bq3 |
| |
| cj = (ci73 ~mod+ ci51) ~mod* $p1_175875602$ |
| |
| ck1 = bq1 ~mod* $p1_501321110$ |
| ck3 = bq3 ~mod* $p3_072711026$ |
| ck5 = bq5 ~mod* $p2_053119869$ |
| ck7 = bq7 ~mod* $p0_298631336$ |
| |
| ci51 ~mod*= $m0_390180644$ |
| ci53 ~mod*= $m2_562915447$ |
| ci71 ~mod*= $m0_899976223$ |
| ci73 ~mod*= $m1_961570560$ |
| |
| cl51 = ci51 ~mod+ cj |
| cl73 = ci73 ~mod+ cj |
| |
| ck1 ~mod+= ci71 ~mod+ cl51 |
| ck3 ~mod+= ci53 ~mod+ cl73 |
| ck5 ~mod+= ci53 ~mod+ cl51 |
| ck7 ~mod+= ci71 ~mod+ cl73 |
| |
| // Combine rows. |
| |
| intermediate[$row0colX$] = this.util.sign_extend_rshift_u32(a: (cd0 ~mod+ ck1) ~mod+ (1 << 10), n: 11) |
| intermediate[$row7colX$] = this.util.sign_extend_rshift_u32(a: (cd0 ~mod- ck1) ~mod+ (1 << 10), n: 11) |
| intermediate[$row1colX$] = this.util.sign_extend_rshift_u32(a: (cd1 ~mod+ ck3) ~mod+ (1 << 10), n: 11) |
| intermediate[$row6colX$] = this.util.sign_extend_rshift_u32(a: (cd1 ~mod- ck3) ~mod+ (1 << 10), n: 11) |
| intermediate[$row2colX$] = this.util.sign_extend_rshift_u32(a: (cd2 ~mod+ ck5) ~mod+ (1 << 10), n: 11) |
| intermediate[$row5colX$] = this.util.sign_extend_rshift_u32(a: (cd2 ~mod- ck5) ~mod+ (1 << 10), n: 11) |
| intermediate[$row3colX$] = this.util.sign_extend_rshift_u32(a: (cd3 ~mod+ ck7) ~mod+ (1 << 10), n: 11) |
| intermediate[$row4colX$] = this.util.sign_extend_rshift_u32(a: (cd3 ~mod- ck7) ~mod+ (1 << 10), n: 11) |
| ` |
| |
| const pass1 = `// ==== Second pass, row $rowY$. |
| |
| // Even columns. |
| |
| in2 = intermediate[$rowYcol2$] |
| in6 = intermediate[$rowYcol6$] |
| |
| ra = (in2 ~mod+ in6) ~mod* $p0_541196100$ |
| |
| rb2 = ra ~mod+ (in2 ~mod* $p0_765366865$) |
| rb6 = ra ~mod- (in6 ~mod* $p1_847759065$) |
| |
| in0 = intermediate[$rowYcol0$] |
| in4 = intermediate[$rowYcol4$] |
| |
| rcp = (in0 ~mod+ in4) ~mod<< 13 |
| rcm = (in0 ~mod- in4) ~mod<< 13 |
| |
| rd0 = rcp ~mod+ rb2 |
| rd1 = rcm ~mod+ rb6 |
| rd2 = rcm ~mod- rb6 |
| rd3 = rcp ~mod- rb2 |
| |
| // Odd columns. |
| |
| in1 = intermediate[$rowYcol1$] |
| in3 = intermediate[$rowYcol3$] |
| in5 = intermediate[$rowYcol5$] |
| in7 = intermediate[$rowYcol7$] |
| |
| ri51 = in5 ~mod+ in1 |
| ri53 = in5 ~mod+ in3 |
| ri71 = in7 ~mod+ in1 |
| ri73 = in7 ~mod+ in3 |
| |
| rj = (ri73 ~mod+ ri51) ~mod* $p1_175875602$ |
| |
| rk1 = in1 ~mod* $p1_501321110$ |
| rk3 = in3 ~mod* $p3_072711026$ |
| rk5 = in5 ~mod* $p2_053119869$ |
| rk7 = in7 ~mod* $p0_298631336$ |
| |
| ri51 ~mod*= $m0_390180644$ |
| ri53 ~mod*= $m2_562915447$ |
| ri71 ~mod*= $m0_899976223$ |
| ri73 ~mod*= $m1_961570560$ |
| |
| rl51 = ri51 ~mod+ rj |
| rl73 = ri73 ~mod+ rj |
| |
| rk1 ~mod+= ri71 ~mod+ rl51 |
| rk3 ~mod+= ri53 ~mod+ rl73 |
| rk5 ~mod+= ri53 ~mod+ rl51 |
| rk7 ~mod+= ri71 ~mod+ rl73 |
| |
| // Combine columns. |
| |
| $bounds_check$ |
| |
| args.dst_buffer[0] = BIAS_AND_CLAMP[(((rd0 ~mod+ rk1) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[7] = BIAS_AND_CLAMP[(((rd0 ~mod- rk1) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[1] = BIAS_AND_CLAMP[(((rd1 ~mod+ rk3) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[6] = BIAS_AND_CLAMP[(((rd1 ~mod- rk3) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[2] = BIAS_AND_CLAMP[(((rd2 ~mod+ rk5) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[5] = BIAS_AND_CLAMP[(((rd2 ~mod- rk5) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[3] = BIAS_AND_CLAMP[(((rd3 ~mod+ rk7) ~mod+ (1 << 17)) >> 18) & 1023] |
| args.dst_buffer[4] = BIAS_AND_CLAMP[(((rd3 ~mod- rk7) ~mod+ (1 << 17)) >> 18) & 1023] |
| |
| $advance$ |
| ` |