Skip to main content

encode_portfolio_f32

Function encode_portfolio_f32 

Source
pub fn encode_portfolio_f32(
    x: &[f32],
    dims: &[usize],
    cfg: &WavConfig,
    screen: bool,
) -> (Vec<u8>, AutoReport)
Expand description

Portfolio encode: encode with every candidate the pre-screen keeps (all applicable ones when screen is false) and keep the smallest stream. The output is one tag byte (counted in the rate) followed by the stream.

Examples found in repository?
examples/tc.rs (line 106)
34fn main() {
35    let args: Vec<String> = std::env::args().skip(1).collect();
36    match args.first().map(String::as_str) {
37        Some("encode") if args.len() >= 3 => {
38            let x = read_f32(&args[1]);
39            let range = {
40                let (a, b) = x
41                    .iter()
42                    .fold((f32::INFINITY, f32::NEG_INFINITY), |(a, b), &v| {
43                        (a.min(v), b.max(v))
44                    });
45                (b - a) as f64
46            };
47            let mut dims = vec![x.len()];
48            let mut bound = None;
49            let mut codec = "wavelet".to_string();
50            let mut rho = None;
51            let mut model = "hand".to_string();
52            let mut i = 3;
53            while i < args.len() {
54                if args[i] == "--fast" {
55                    codec = "fast".to_string();
56                    i += 1;
57                    continue;
58                }
59                let v = args.get(i + 1).cloned().unwrap_or_else(|| usage());
60                match args[i].as_str() {
61                    "--dims" => dims = v.split('x').map(|s| s.parse().unwrap()).collect(),
62                    "--psnr" => bound = Some(ErrorBound::Psnr(v.parse().unwrap())),
63                    "--rmse" => bound = Some(ErrorBound::Rmse(v.parse().unwrap())),
64                    "--max-abs" => bound = Some(ErrorBound::MaxAbs(v.parse().unwrap())),
65                    "--max-rel" => {
66                        bound = Some(ErrorBound::MaxAbs(v.parse::<f64>().unwrap() * range))
67                    }
68                    "--codec" => codec = v,
69                    "--rho" => rho = Some(v.parse().unwrap()),
70                    "--model" => model = v,
71                    _ => usage(),
72                }
73                i += 2;
74            }
75            let bound = bound.unwrap_or_else(|| usage());
76            let t = Instant::now();
77            let (bytes, json) = match codec.as_str() {
78                "wavelet" => {
79                    let mut cfg = wavcodec::WavConfig::new(bound);
80                    if let Some(r) = rho {
81                        cfg.rho = r;
82                    }
83                    cfg.model = cram_codec::learned::parse_model_arg(&model);
84                    let (b, s) = wavcodec::encode_f32(&x, &dims, &cfg);
85                    let j = format!(
86                        "\"coef_bytes\":{},\"model_bytes\":{},\"outlier_bytes\":{},\"n_outliers\":{},\"delta\":{},\"rmse\":{},\"max_abs\":{},\"passes\":{}",
87                        s.coef_bytes, s.model_bytes, s.outlier_bytes, s.n_outliers, s.delta, s.rmse, s.max_abs, s.passes
88                    );
89                    (b, j)
90                }
91                "tucker" => {
92                    let (b, s) = cram_codec::tucker::encode_f32(&x, &dims, bound);
93                    let j = format!(
94                        "\"core_bytes\":{},\"factor_bytes\":{},\"ranks\":{:?},\"delta\":{},\"rmse\":{},\"max_abs\":{}",
95                        s.core_bytes, s.factor_bytes, s.ranks, s.delta, s.rmse, s.max_abs
96                    );
97                    (b, j)
98                }
99                "auto" | "portfolio-all" => {
100                    let mut cfg = wavcodec::WavConfig::new(bound);
101                    if let Some(r) = rho {
102                        cfg.rho = r;
103                    }
104                    cfg.model = cram_codec::learned::parse_model_arg(&model);
105                    let (b, rep) =
106                        cram_codec::encode_portfolio_f32(&x, &dims, &cfg, codec == "auto");
107                    let tried: Vec<String> = rep
108                        .tried
109                        .iter()
110                        .map(|(c, n, t)| format!("\"{}:{n}:{t:.3}\"", c.name()))
111                        .collect();
112                    (
113                        b,
114                        format!(
115                            "\"chose\":\"{}\",\"probe_rank\":{},\"tried\":[{}]",
116                            rep.pick.name(),
117                            rep.probe_rank,
118                            tried.join(",")
119                        ),
120                    )
121                }
122                "fast" => {
123                    let mut cfg = wavcodec::WavConfig::new(bound);
124                    cfg.model = cram_codec::learned::parse_model_arg(&model);
125                    let (b, c) = cram_codec::encode_fast_f32(&x, &dims, &cfg);
126                    (b, format!("\"chose\":\"{}\"", c.name()))
127                }
128                "qtt-probe" => {
129                    let env = |k: &str, d: usize| {
130                        std::env::var(k)
131                            .ok()
132                            .and_then(|v| v.parse().ok())
133                            .unwrap_or(d)
134                    };
135                    let (n, r, t) = cram_codec::qtt_probe(
136                        &x,
137                        &dims,
138                        bound,
139                        env("PROBE_STRIDE", 2),
140                        env("PROBE_CAP", 32),
141                    );
142                    (
143                        vec![0u8; n],
144                        format!("\"probe_bytes\":{n},\"probe_rank\":{r},\"probe_s\":{t}"),
145                    )
146                }
147                "interp" | "lorenzo" | "qtt" | "qtt-sparse" => {
148                    let cfg = wavcodec::WavConfig::new(bound);
149                    let c = match codec.as_str() {
150                        "qtt" => cram_codec::Candidate::Qtt,
151                        "qtt-sparse" => cram_codec::Candidate::QttSparse,
152                        "lorenzo" => cram_codec::Candidate::Lorenzo,
153                        _ => cram_codec::Candidate::Interp,
154                    };
155                    let mut b = vec![c.tag()];
156                    b.extend(cram_codec::encode_candidate_f32(c, &x, &dims, &cfg));
157                    (b, format!("\"chose\":\"{codec}\""))
158                }
159                _ => usage(),
160            };
161            let enc = t.elapsed().as_secs_f64();
162            std::fs::write(&args[2], &bytes).unwrap();
163            println!(
164                "{{\"bytes\":{},\"bpv\":{},\"encode_s\":{enc},{json}}}",
165                bytes.len(),
166                8.0 * bytes.len() as f64 / x.len() as f64
167            );
168        }
169        Some("decode") if args.len() == 3 || (args.len() == 5 && args[3] == "--model") => {
170            if args.len() == 5 {
171                // registers a pretrained network so the decoder can resolve it
172                let _ = cram_codec::learned::parse_model_arg(&args[4]);
173            }
174            let bytes = std::fs::read(&args[1]).unwrap();
175            let t = Instant::now();
176            let Decoded::F32 { data, .. } = decode_any(&bytes).expect("decode") else {
177                panic!("not an f32 stream")
178            };
179            let dec = t.elapsed().as_secs_f64();
180            let out: Vec<u8> = data.iter().flat_map(|v| v.to_le_bytes()).collect();
181            std::fs::write(&args[2], out).unwrap();
182            println!("{{\"decode_s\":{dec}}}");
183        }
184        _ => usage(),
185    }
186}