未验证 提交 2f829cd1 编写于 作者: P Peter Pan 提交者: GitHub

fix #672 (#673)

* chore: code polishment

* fix: calculate step width in tooltip (#672)
上级 7bdb74b1
import LineChart, {LineChartRef} from '~/components/LineChart';
import {
Dataset,
Range,
ScalarDataset,
SortingMethod,
XAxis,
chartData,
......@@ -13,7 +14,6 @@ import {
transform,
xAxisMap
} from '~/resource/scalars';
import LineChart, {LineChartRef} from '~/components/LineChart';
import React, {FunctionComponent, useCallback, useMemo, useRef, useState} from 'react';
import {rem, size} from '~/utils/style';
......@@ -22,6 +22,7 @@ import {EChartOption} from 'echarts';
import {Run} from '~/types';
import {cycleFetcher} from '~/utils/fetch';
import ee from '~/utils/event';
import {format} from 'd3-format';
import queryString from 'query-string';
import styled from 'styled-components';
import useHeavyWork from '~/hooks/useHeavyWork';
......@@ -110,7 +111,7 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
const echart = useRef<LineChartRef>(null);
const {data: datasets, error, loading} = useRunningRequest<(Dataset | null)[]>(
const {data: datasets, error, loading} = useRunningRequest<(ScalarDataset | null)[]>(
runs.map(run => `/scalars/list?${queryString.stringify({run: run.label, tag})}`),
!!running,
(...urls) => cycleFetcher(urls)
......@@ -171,15 +172,20 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
[smoothedDatasets, runs, xAxis]
);
const maxStepLength = useMemo(
() => String(Math.max(...smoothedDatasets.map(i => Math.max(...i.map(j => j[1]))))).length,
[smoothedDatasets]
);
const formatter = useCallback(
(params: EChartOption.Tooltip.Format | EChartOption.Tooltip.Format[]) => {
const data = Array.isArray(params) ? params[0].data : params.data;
const step = data[1];
const points = nearestPoint(smoothedDatasets ?? [], runs, step);
const sort = sortingMethodMap[sortingMethod];
return tooltip(sort ? sort(points, data) : points, i18n);
return tooltip(sort ? sort(points, data) : points, maxStepLength, i18n);
},
[smoothedDatasets, runs, sortingMethod, i18n]
[smoothedDatasets, runs, sortingMethod, maxStepLength, i18n]
);
const options = useMemo(
......@@ -191,7 +197,13 @@ const ScalarChart: FunctionComponent<ScalarChartProps> = ({
},
xAxis: {
type: xAxisType,
...ranges.x
...ranges.x,
axisPointer: {
label: {
formatter:
xAxisType === XAxisType.time ? undefined : ({value}: {value: number}) => format('.8')(value)
}
}
},
yAxis: {
type: yAxisType,
......
......@@ -65,7 +65,7 @@ export const chartData = ({data, runs, xAxis}: {data: Dataset[]; runs: Run[]; xA
.flat();
// TODO: make it better, don't concat html
export const tooltip = (data: TooltipData[], i18n: I18n) => {
export const tooltip = (data: TooltipData[], stepLength: number, i18n: I18n) => {
const indexPropMap = {
time: 0,
step: 1,
......@@ -73,10 +73,10 @@ export const tooltip = (data: TooltipData[], i18n: I18n) => {
smoothed: 3,
relative: 4
} as const;
const widthPropMap = {
run: [60, 180] as [number, number],
const widthPropMap: Record<string, number | readonly [number, number]> = {
run: [60, 180],
time: 150,
step: 40,
step: Math.max(stepLength * 8, 40),
value: 60,
smoothed: 70,
relative: 60
......@@ -103,7 +103,7 @@ export const tooltip = (data: TooltipData[], i18n: I18n) => {
} as const;
});
const renderContent = (content: string, width: number | [number, number]) =>
const renderContent = (content: string, width: number | readonly [number, number]) =>
`<div style="overflow: hidden; ${
Array.isArray(width)
? `min-width:${(width as [number, number])[0]};max-width:${(width as [number, number])[1]};`
......
import {Dataset, ScalarDataset} from './types';
import BigNumber from 'bignumber.js';
import {Dataset} from './types';
import {Run} from '~/types';
import cloneDeep from 'lodash/cloneDeep';
import compact from 'lodash/compact';
import maxBy from 'lodash/maxBy';
import minBy from 'lodash/minBy';
import {quantile} from '~/utils';
export const transform = ({datasets, smoothing}: {datasets: Dataset[]; smoothing: number}) =>
export const transform = ({datasets, smoothing}: {datasets: ScalarDataset[]; smoothing: number}) =>
// https://en.wikipedia.org/wiki/Moving_average
datasets.map(seriesData => {
const data = cloneDeep(seriesData);
const data = seriesData.map<Dataset[number]>(s => [...s, Number.NaN, Number.NaN]);
let last = new BigNumber(data.length > 0 ? 0 : Number.NaN);
let numAccum = 0;
let startValue = 0;
......
......@@ -2,7 +2,14 @@ import {sortingMethodMap, xAxisMap} from './index';
import {Run} from '~/types';
export type Dataset = number[][];
type Value = number;
type WallTime = number;
type Step = number;
type Smoothed = number;
type Relative = number;
export type Dataset = [WallTime, Step, Value, Smoothed, Relative][];
export type ScalarDataset = [WallTime, Step, Value][];
export type XAxis = keyof typeof xAxisMap;
export type SortingMethod = keyof typeof sortingMethodMap;
......
......@@ -59,8 +59,7 @@ export const tooltip = {
axisPointer: {
type: 'cross',
label: {
show: true,
formatter: ({value}: {value: number}) => format('.4')(value)
show: true
},
lineStyle: {
color: '#2932E1',
......
......@@ -2,9 +2,9 @@
# It is not intended for manual editing.
[[package]]
name = "bumpalo"
version = "3.2.0"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]]
name = "cfg-if"
......@@ -119,15 +119,15 @@ dependencies = [
[[package]]
name = "itoa"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "js-sys"
version = "0.3.36"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5"
checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177"
dependencies = [
"wasm-bindgen",
]
......@@ -161,18 +161,18 @@ checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
[[package]]
name = "pin-project"
version = "0.4.20"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e75373ff9037d112bb19bc61333a06a159eaeb217660dcfbea7d88e1db823919"
checksum = "12e3a6cdbfe94a5e4572812a0201f8c0ed98c1c452c7b8563ce2276988ef9c17"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.20"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10b4b44893d3c370407a1d6a5cfde7c41ae0478e31c516c85f67eb3adc51be6d"
checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7"
dependencies = [
"proc-macro2",
"quote",
......@@ -187,44 +187,39 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-hack"
version = "0.5.11"
version = "0.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
[[package]]
name = "proc-macro-nested"
version = "0.1.3"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
[[package]]
name = "proc-macro2"
version = "1.0.9"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.3"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.2"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scoped-tls"
......@@ -234,15 +229,15 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "serde"
version = "1.0.104"
version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
checksum = "736aac72d1eafe8e5962d1d1c3d99b0df526015ba40915cb3c49d042e92ec243"
[[package]]
name = "serde_derive"
version = "1.0.104"
version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
checksum = "bf0343ce212ac0d3d6afd9391ac8e9c9efe06b533c8d33f660f6390cc4093f57"
dependencies = [
"proc-macro2",
"quote",
......@@ -251,9 +246,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.48"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
dependencies = [
"itoa",
"ryu",
......@@ -268,9 +263,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "syn"
version = "1.0.16"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
dependencies = [
"proc-macro2",
"quote",
......@@ -300,9 +295,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.59"
version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d"
checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0"
dependencies = [
"cfg-if",
"serde",
......@@ -312,9 +307,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.59"
version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8"
checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101"
dependencies = [
"bumpalo",
"lazy_static",
......@@ -327,9 +322,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.9"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "457414a91863c0ec00090dba537f88ab955d93ca6555862c29b6d860990b8a8a"
checksum = "64487204d863f109eb77e8462189d111f27cb5712cc9fdb3461297a76963a2f6"
dependencies = [
"cfg-if",
"js-sys",
......@@ -339,9 +334,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.59"
version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205"
checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
......@@ -349,9 +344,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.59"
version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d"
checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92"
dependencies = [
"proc-macro2",
"quote",
......@@ -362,15 +357,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.59"
version = "0.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8"
checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.9"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449aeba7035e4a4710cd263bbac33519fa3828bff1c6f642fa8896601e7016ad"
checksum = "0f0dfda4d3b3f8acbc3c291b09208081c203af457fb14a229783b06e2f128aa7"
dependencies = [
"console_error_panic_hook",
"js-sys",
......@@ -382,9 +377,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.9"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49449f8dcedc192bd0cf11b5711982decdd4dbad1029f92370e2b1215031dd59"
checksum = "2c2e18093f11c19ca4e188c177fecc7c372304c311189f12c2f9bea5b7324ac7"
dependencies = [
"proc-macro2",
"quote",
......@@ -392,9 +387,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.36"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a"
checksum = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17"
dependencies = [
"js-sys",
"wasm-bindgen",
......
......@@ -25,13 +25,13 @@ lto = true
# default = ["wee_alloc"]
[dependencies]
serde = "1.0.104"
serde_derive = "1.0.104"
serde = "1.0.112"
serde_derive = "1.0.112"
# The `wasm-bindgen` crate provides the bare minimum functionality needed
# to interact with JavaScript.
[dependencies.wasm-bindgen]
version = "0.2.59"
version = "0.2.63"
features = ["serde-serialize"]
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
......@@ -42,7 +42,7 @@ features = ["serde-serialize"]
# The `web-sys` crate allows you to interact with the various browser APIs,
# like the DOM.
[dependencies.web-sys]
version = "0.3.36"
version = "0.3.40"
features = ["console"]
# The `console_error_panic_hook` crate provides better debugging of panics by
......@@ -54,10 +54,10 @@ console_error_panic_hook = "0.1.6"
# These crates are used for running unit tests.
[dev-dependencies]
wasm-bindgen-test = "0.3.6"
wasm-bindgen-test = "0.3.13"
futures = "0.3.5"
js-sys = "0.3.36"
wasm-bindgen-futures = "0.4.9"
js-sys = "0.3.40"
wasm-bindgen-futures = "0.4.13"
[package.metadata.wasm-pack.profile.dev]
# Should `wasm-opt` be used to further optimize the wasm binary generated after
......
......@@ -5,9 +5,9 @@ pub struct Point {
showing: bool,
}
impl Point {
pub fn new(name: String, value: Vec<f64>, showing: bool) -> Self {
pub fn new(name: &str, value: Vec<f64>, showing: bool) -> Self {
Point {
name,
name: String::from(name),
value,
showing,
}
......@@ -23,25 +23,27 @@ impl DividedPoints {
}
pub fn divide(
points: Vec<Vec<f64>>,
labels: Vec<String>,
points: &Vec<Vec<f64>>,
labels: &Vec<String>,
visibility: bool,
keyword: String,
keyword: &str,
) -> DividedPoints {
let mut matched: Vec<Point> = vec![];
let mut missing: Vec<Point> = vec![];
for (i, point) in points.iter().enumerate() {
let mut name: String = String::from("");
let mut name: &str = "";
let ptr: *const String = &labels[i];
if !ptr.is_null() {
name = labels[i].clone();
unsafe {
name = &(*ptr)[..];
}
}
let point_with_label: Point = Point::new(name.clone(), point.to_vec(), visibility);
if keyword == String::from("") {
let point_with_label: Point = Point::new(name, point.to_vec(), visibility);
if let "" = keyword {
missing.push(point_with_label);
} else {
if name.contains(&keyword) {
if String::from(name).contains(&keyword) {
matched.push(point_with_label);
} else {
missing.push(point_with_label);
......
use std::f64;
trait FloatIterExt {
fn float_min(&mut self) -> f64;
fn float_max(&mut self) -> f64;
......@@ -108,7 +106,7 @@ fn compute_histogram(
return result;
}
pub fn transform_overlay(data: Vec<Data>) -> Overlay {
pub fn transform_overlay(data: &Vec<Data>) -> Overlay {
struct Temp {
time: f64,
step: f64,
......@@ -154,8 +152,8 @@ pub fn transform_overlay(data: Vec<Data>) -> Overlay {
};
}
pub fn transform_offset(data: Vec<Data>) -> Offset {
let overlay: Overlay = transform_overlay(data);
pub fn transform_offset(data: &Vec<Data>) -> Offset {
let overlay: Overlay = transform_overlay(&data);
let mut min_step: f64 = std::f64::INFINITY;
let mut max_step: f64 = std::f64::NEG_INFINITY;
let mut min_z: f64 = std::f64::INFINITY;
......
......@@ -14,31 +14,33 @@ pub fn main() {}
pub fn scalar_transform(js_datasets: &JsValue, smoothing: f64) -> JsValue {
utils::set_panic_hook();
let datasets: Vec<Vec<scalar::Dataset>> = js_datasets.into_serde().unwrap();
let result: Vec<Vec<scalar::Smoothed>> = scalar::transform(datasets, smoothing);
return JsValue::from_serde(&result).unwrap();
let result: Vec<Vec<scalar::Smoothed>> = scalar::transform(&datasets, smoothing);
JsValue::from_serde(&result).unwrap()
}
#[wasm_bindgen]
pub fn scalar_range(js_datasets: &JsValue, outlier: bool) -> JsValue {
utils::set_panic_hook();
let datasets: Vec<Vec<scalar::Smoothed>> = js_datasets.into_serde().unwrap();
let result = scalar::range(datasets, outlier);
return JsValue::from_serde(&result).unwrap();
let result = scalar::range(&datasets, outlier);
JsValue::from_serde(&result).unwrap()
}
#[wasm_bindgen]
pub fn histogram_transform(js_data: &JsValue, mode: String) -> JsValue {
pub fn histogram_transform(js_data: &JsValue, mode: &str) -> JsValue {
utils::set_panic_hook();
let data: Vec<histogram::Data> = js_data.into_serde().unwrap();
if mode == String::from("overlay") {
let result = histogram::transform_overlay(data);
return JsValue::from_serde(&result).unwrap();
match mode {
"overlay" => {
let result = histogram::transform_overlay(&data);
JsValue::from_serde(&result).unwrap()
}
"offset" => {
let result = histogram::transform_offset(&data);
JsValue::from_serde(&result).unwrap()
}
_ => JsValue::null(),
}
if mode == String::from("offset") {
let result = histogram::transform_offset(data);
return JsValue::from_serde(&result).unwrap();
}
return JsValue::null();
}
#[wasm_bindgen]
......@@ -46,12 +48,12 @@ pub fn high_dimensional_divide(
js_points: &JsValue,
js_labels: &JsValue,
visibility: bool,
keyword: String,
keyword: &str,
) -> JsValue {
utils::set_panic_hook();
let points: Vec<Vec<f64>> = js_points.into_serde().unwrap();
let labels: Vec<String> = js_labels.into_serde().unwrap();
let result: high_dimensional::DividedPoints =
high_dimensional::divide(points, labels, visibility, keyword);
return JsValue::from_serde(&result).unwrap();
high_dimensional::divide(&points, &labels, visibility, keyword);
JsValue::from_serde(&result).unwrap()
}
......@@ -15,7 +15,7 @@ impl Range {
}
}
fn quantile(values: Vec<f64>, p: f64) -> f64 {
fn quantile(values: &Vec<f64>, p: f64) -> f64 {
let n: usize = values.len();
if n == 0 {
return std::f64::NAN;
......@@ -33,7 +33,7 @@ fn quantile(values: Vec<f64>, p: f64) -> f64 {
return value0 + (value1 - value0) * (i - (i0 as f64));
}
pub fn transform(datasets: Vec<Vec<Dataset>>, smoothing: f64) -> Vec<Vec<Smoothed>> {
pub fn transform(datasets: &Vec<Vec<Dataset>>, smoothing: f64) -> Vec<Vec<Smoothed>> {
let mut result: Vec<Vec<Smoothed>> = vec![];
for dataset in datasets.iter() {
let mut row: Vec<Smoothed> = vec![];
......@@ -72,7 +72,7 @@ pub fn transform(datasets: Vec<Vec<Dataset>>, smoothing: f64) -> Vec<Vec<Smoothe
return result;
}
pub fn range(datasets: Vec<Vec<Smoothed>>, outlier: bool) -> Range {
pub fn range(datasets: &Vec<Vec<Smoothed>>, outlier: bool) -> Range {
let mut ranges: Vec<Range> = vec![];
for data in datasets.iter() {
......@@ -90,8 +90,8 @@ pub fn range(datasets: Vec<Vec<Smoothed>>, outlier: bool) -> Range {
ranges.push(Range::new(sorted[0], sorted[n - 1]));
} else {
ranges.push(Range::new(
quantile(sorted, 0.05_f64),
quantile(values, 0.95),
quantile(&sorted, 0.05_f64),
quantile(&values, 0.95),
));
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册