[READ-ONLY] Mirror of https://github.com/probablykasper/cpc. Text calculator with support for units and conversion cpc.kasper.space
calculator cli conversion converter library math package units units-converter wasm website
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: add computational work and computational perf units (#43)

* feat: add computational work and computational perf units

Add support for computational work (FLOP) and computational performance
(FLOP per second) units.

* Rename UnitType

* Change unit casing

* Update CHANGELOG.md

* Rename to FlopCount

* Fix renames

---------

Co-authored-by: Kasper <kasperkh.kh@gmail.com>

authored by

Gabriel dos Santos
Kasper
and committed by
GitHub
(Jun 20, 2026, 1:57 AM +0200) b72bdba6 dffab506

+202 -11
+1
CHANGELOG.md
··· 1 1 # Changelog 2 2 3 3 ## Next 4 + - Add FLOP and FLOPS units 4 5 - Update `fastnum` dependency 5 6 - Fix conversion of `torr`, `btu/s` and `btu/h` 6 7 - Fix unit spellings
+9 -8
README.md
··· 49 49 50 50 ## Supported unit types 51 51 - Normal numbers 52 - - Time 53 - - Length 54 52 - Area 55 - - Volume 56 - - Mass 57 53 - Digital storage (bytes etc) 54 + - Electric current 58 55 - Energy 56 + - FLOPS 57 + - Frequency 58 + - Length 59 + - Mass 59 60 - Power 60 - - Electric current 61 - - Resistance 62 - - Voltage 63 61 - Pressure 64 - - Frequency 62 + - Resistance 65 63 - Speed 66 64 - Temperature 65 + - Time 66 + - Voltage 67 + - Volume 67 68 68 69 ## API Installation 69 70 Add `cpc` as a dependency in `Cargo.toml`.
+112
src/lexer.rs
··· 428 428 "zbps" => Token::Unit(ZettabitsPerSecond), 429 429 "ybps" => Token::Unit(YottabitsPerSecond), 430 430 431 + "flop" => Token::Unit(Flop), 432 + "kflop" | "kiloflop" => Token::Unit(KiloFlop), 433 + "mflop" | "megaflop" => Token::Unit(MegaFlop), 434 + "gflop" | "gigaflop" => Token::Unit(GigaFlop), 435 + "tflop" | "teraflop" => Token::Unit(TeraFlop), 436 + "pflop" | "petaflop" => Token::Unit(PetaFlop), 437 + "eflop" | "exaflop" => Token::Unit(ExaFlop), 438 + "zflop" | "zettaflop" => Token::Unit(ZettaFlop), 439 + "yflop" | "yottaflop" => Token::Unit(YottaFlop), 440 + "rflop" | "ronnaflop" => Token::Unit(RonnaFlop), 441 + "qflop" | "quettaflop" => Token::Unit(QuettaFlop), 442 + 443 + "flops" => Token::Unit(FlopPerSecond), 444 + "kflops" | "kiloflops" => Token::Unit(KiloFlopPerSecond), 445 + "mflops" | "megaflops" => Token::Unit(MegaFlopPerSecond), 446 + "gflops" | "gigaflops" => Token::Unit(GigaFlopPerSecond), 447 + "tflops" | "teraflops" => Token::Unit(TeraFlopPerSecond), 448 + "pflops" | "petaflops" => Token::Unit(PetaFlopPerSecond), 449 + "eflops" | "exaflops" => Token::Unit(ExaFlopPerSecond), 450 + "zflops" | "zettaflops" => Token::Unit(ZettaFlopPerSecond), 451 + "yflops" | "yottaflops" => Token::Unit(YottaFlopPerSecond), 452 + "rflops" | "ronnaflops" => Token::Unit(RonnaFlopPerSecond), 453 + "qflops" | "quettaflops" => Token::Unit(QuettaFlopPerSecond), 454 + 431 455 "millijoule" | "millijoules" => Token::Unit(Millijoule), 432 456 "j"| "joule" | "joules" => Token::Unit(Joule), 433 457 "nm" => Token::Unit(NewtonMeter), ··· 883 907 (Token::Unit(Yobibyte), Token::LexerKeyword(Per), Token::Unit(Second)) => { 884 908 tokens[token_index-2] = Token::Unit(YobibytesPerSecond); 885 909 }, 910 + // FLOP per second 911 + (Token::Unit(Flop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 912 + tokens[token_index-2] = Token::Unit(FlopPerSecond); 913 + }, 914 + // kiloFLOP per second 915 + (Token::Unit(KiloFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 916 + tokens[token_index-2] = Token::Unit(KiloFlopPerSecond); 917 + }, 918 + // megaFLOP per second 919 + (Token::Unit(MegaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 920 + tokens[token_index-2] = Token::Unit(MegaFlopPerSecond); 921 + }, 922 + // gigaFLOP per second 923 + (Token::Unit(GigaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 924 + tokens[token_index-2] = Token::Unit(GigaFlopPerSecond); 925 + }, 926 + // teraFLOP per second 927 + (Token::Unit(TeraFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 928 + tokens[token_index-2] = Token::Unit(TeraFlopPerSecond); 929 + }, 930 + // petaFLOP per second 931 + (Token::Unit(PetaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 932 + tokens[token_index-2] = Token::Unit(PetaFlopPerSecond); 933 + }, 934 + // exaFLOP per second 935 + (Token::Unit(ExaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 936 + tokens[token_index-2] = Token::Unit(ExaFlopPerSecond); 937 + }, 938 + // zettaFLOP per second 939 + (Token::Unit(ZettaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 940 + tokens[token_index-2] = Token::Unit(ZettaFlopPerSecond); 941 + }, 942 + // yottaFLOP per second 943 + (Token::Unit(YottaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 944 + tokens[token_index-2] = Token::Unit(YottaFlopPerSecond); 945 + }, 946 + // ronnaFLOP per second 947 + (Token::Unit(RonnaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 948 + tokens[token_index-2] = Token::Unit(RonnaFlopPerSecond); 949 + }, 950 + // quettaFLOP per second 951 + (Token::Unit(QuettaFlop), Token::LexerKeyword(Per), Token::Unit(Second)) => { 952 + tokens[token_index-2] = Token::Unit(QuettaFlopPerSecond); 953 + }, 886 954 // btu/min 887 955 (Token::Unit(BritishThermalUnit), Token::LexerKeyword(Per), Token::Unit(Minute)) => { 888 956 tokens[token_index-2] = Token::Unit(BritishThermalUnitsPerMinute); ··· 1085 1153 run_datarate_lex("18 exbibytes per second", vec![numtok!(18), Token::Unit(ExbibytesPerSecond)]); 1086 1154 run_datarate_lex("19 zebibytes per second", vec![numtok!(19), Token::Unit(ZebibytesPerSecond)]); 1087 1155 run_datarate_lex("20 yobibytes per second", vec![numtok!(20), Token::Unit(YobibytesPerSecond)]); 1156 + run_lex("1 flop", vec![numtok!(1), Token::Unit(Flop)]); 1157 + run_lex("2 kflop", vec![numtok!(2), Token::Unit(KiloFlop)]); 1158 + run_lex("3 mflop", vec![numtok!(3), Token::Unit(MegaFlop)]); 1159 + run_lex("4 gflop", vec![numtok!(4), Token::Unit(GigaFlop)]); 1160 + run_lex("5 tflop", vec![numtok!(5), Token::Unit(TeraFlop)]); 1161 + run_lex("6 pflop", vec![numtok!(6), Token::Unit(PetaFlop)]); 1162 + run_lex("7 eflop", vec![numtok!(7), Token::Unit(ExaFlop)]); 1163 + run_lex("8 zflop", vec![numtok!(8), Token::Unit(ZettaFlop)]); 1164 + run_lex("9 yflop", vec![numtok!(9), Token::Unit(YottaFlop)]); 1165 + run_lex("10 rflop", vec![numtok!(10), Token::Unit(RonnaFlop)]); 1166 + run_lex("11 qflop", vec![numtok!(11), Token::Unit(QuettaFlop)]); 1167 + run_lex("1 flop/s", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1168 + run_lex("2 kflop/s", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1169 + run_lex("3 mflop/s", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); 1170 + run_lex("4 gflop/s", vec![numtok!(4), Token::Unit(GigaFlopPerSecond)]); 1171 + run_lex("5 tflop/s", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1172 + run_lex("6 pflop/s", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1173 + run_lex("7 eflop/s", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1174 + run_lex("8 zflop/s", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1175 + run_lex("9 yflop/s", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1176 + run_lex("10 rflop/s", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1177 + run_lex("11 qflop/s", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1178 + run_lex("1 flop per second", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1179 + run_lex("2 kflop per second", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1180 + run_lex("3 mflop per second", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); 1181 + run_lex("4 gflop per second", vec![numtok!(4), Token::Unit(GigaFlopPerSecond)]); 1182 + run_lex("5 tflop per second", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1183 + run_lex("6 pflop per second", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1184 + run_lex("7 eflop per second", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1185 + run_lex("8 zflop per second", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1186 + run_lex("9 yflop per second", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1187 + run_lex("10 rflop per second", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1188 + run_lex("11 qflop per second", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1189 + run_lex("1 flops", vec![numtok!(1), Token::Unit(FlopPerSecond)]); 1190 + run_lex("2 kflops", vec![numtok!(2), Token::Unit(KiloFlopPerSecond)]); 1191 + run_lex("3 mflops", vec![numtok!(3), Token::Unit(MegaFlopPerSecond)]); 1192 + run_lex("4 gflops", vec![numtok!(4), Token::Unit(GigaFlopPerSecond)]); 1193 + run_lex("5 tflops", vec![numtok!(5), Token::Unit(TeraFlopPerSecond)]); 1194 + run_lex("6 pflops", vec![numtok!(6), Token::Unit(PetaFlopPerSecond)]); 1195 + run_lex("7 eflops", vec![numtok!(7), Token::Unit(ExaFlopPerSecond)]); 1196 + run_lex("8 zflops", vec![numtok!(8), Token::Unit(ZettaFlopPerSecond)]); 1197 + run_lex("9 yflops", vec![numtok!(9), Token::Unit(YottaFlopPerSecond)]); 1198 + run_lex("10 rflops", vec![numtok!(10), Token::Unit(RonnaFlopPerSecond)]); 1199 + run_lex("11 qflops", vec![numtok!(11), Token::Unit(QuettaFlopPerSecond)]); 1088 1200 run_lex("234 wh", vec![numtok!(234), Token::Unit(WattHour)]); 1089 1201 run_lex("1 w", vec![numtok!(1), Token::Unit(Watt)]); 1090 1202 run_lex("1 watt", vec![numtok!(1), Token::Unit(Watt)]);
+80 -3
src/units.rs
··· 21 21 DigitalStorage, 22 22 /// A unit of data rate transfer, for example [`KilobytesPerSecond`] 23 23 DataTransferRate, 24 + /// A unit of computational work, for example [`KiloFLOP`] 25 + FlopCount, 26 + /// A unit of computational performance, for example [`KiloFLOPPerSecond`] 27 + FlopRate, 24 28 /// A unit of energy, for example [`Joule`] or [`KilowattHour`] 25 29 Energy, 26 30 /// A unit of power, for example [`Watt`] ··· 238 242 ExbibytesPerSecond: (DataTransferRate, d!(9223372036854775808), "exbibyte per second", "exbibytes per second"), 239 243 ZebibytesPerSecond: (DataTransferRate, d!(9444732965739290427392), "zebibyte per second", "zebibytes per second"), 240 244 YobibytesPerSecond: (DataTransferRate, d!(9671406556917033397649408), "yobibyte per second", "yobibytes per second"), 245 + 246 + Flop: (FlopCount, d!(1), "FLOP", "FLOP"), 247 + KiloFlop: (FlopCount, d!(1000), "kiloFLOP", "kiloFLOP"), 248 + MegaFlop: (FlopCount, d!(1000000), "megaFLOP", "megaFLOP"), 249 + GigaFlop: (FlopCount, d!(1000000000), "gigaFLOP", "gigaFLOP"), 250 + TeraFlop: (FlopCount, d!(1000000000000), "teraFLOP", "teraFLOP"), 251 + PetaFlop: (FlopCount, d!(1000000000000000), "petaFLOP", "petaFLOP"), 252 + ExaFlop: (FlopCount, d!(1000000000000000000), "exaFLOP", "exaFLOP"), 253 + ZettaFlop: (FlopCount, d!(1000000000000000000000), "zettaFLOP", "zettaFLOP"), 254 + YottaFlop: (FlopCount, d!(1000000000000000000000000), "yottaFLOP", "yottaFLOP"), 255 + RonnaFlop: (FlopCount, d!(1000000000000000000000000000), "ronnaFLOP", "ronnaFLOP"), 256 + QuettaFlop: (FlopCount, d!(1000000000000000000000000000000), "quettaFLOP", "quettaFLOP"), 257 + 258 + FlopPerSecond: (FlopRate, d!(1), "FLOP per second", "FLOP per second"), 259 + KiloFlopPerSecond: (FlopRate, d!(1000), "kiloFLOP per second", "kiloFLOP per second"), 260 + MegaFlopPerSecond: (FlopRate, d!(1000000), "megaFLOP per second", "megaFLOP per second"), 261 + GigaFlopPerSecond: (FlopRate, d!(1000000000), "gigaFLOP per second", "gigaFLOP per second"), 262 + TeraFlopPerSecond: (FlopRate, d!(1000000000000), "teraFLOP per second", "teraFLOP per second"), 263 + PetaFlopPerSecond: (FlopRate, d!(1000000000000000), "petaFLOP per second", "petaFLOP per second"), 264 + ExaFlopPerSecond: (FlopRate, d!(1000000000000000000), "exaFLOP per second", "exaFLOP per second"), 265 + ZettaFlopPerSecond: (FlopRate, d!(1000000000000000000000), "zettaFLOP per second", "zettaFLOP per second"), 266 + YottaFlopPerSecond: (FlopRate, d!(1000000000000000000000000), "yottaFLOP per second", "yottaFLOP per second"), 267 + RonnaFlopPerSecond: (FlopRate, d!(1000000000000000000000000000), "ronnaFLOP per second", "ronnaFLOP per second"), 268 + QuettaFlopPerSecond: (FlopRate, d!(1000000000000000000000000000000), "quettaFLOP per second", "quettaFLOP per second"), 241 269 242 270 Millijoule: (Energy, d!(0.001), "millijoule", "millijoules"), 243 271 Joule: (Energy, d!(1), "joule", "joules"), ··· 629 657 }; 630 658 let data_storage = Number::new(result, Bit); 631 659 Ok(convert(data_storage, final_unit)?) 660 + } else if lcat == FlopRate && rcat == Time { 661 + // 8 megaFLOP per second * 1 minute 662 + let compute_perf_value = left.value * left.unit.weight(); 663 + let seconds = convert(right, Second)?; 664 + let result = compute_perf_value * seconds.value; 665 + let final_unit = match left.unit { 666 + FlopPerSecond => Flop, 667 + KiloFlopPerSecond => KiloFlop, 668 + MegaFlopPerSecond => MegaFlop, 669 + GigaFlopPerSecond => GigaFlop, 670 + TeraFlopPerSecond => TeraFlop, 671 + PetaFlopPerSecond => PetaFlop, 672 + ExaFlopPerSecond => ExaFlop, 673 + ZettaFlopPerSecond => ZettaFlop, 674 + YottaFlopPerSecond => YottaFlop, 675 + RonnaFlopPerSecond => RonnaFlop, 676 + QuettaFlopPerSecond => QuettaFlop, 677 + _ => Flop, 678 + }; 679 + let compute_work = Number::new(result, Flop); 680 + Ok(convert(compute_work, final_unit)?) 632 681 } else if lcat == Voltage && rcat == ElectricCurrent { 633 682 // 1 volt * 1 ampere = 1 watt 634 683 let result = (left.value * left.unit.weight()) * (right.value * right.unit.weight()); ··· 712 761 let bits = convert(left, Bit)?; 713 762 let bits_per_second = convert(right, BitsPerSecond)?; 714 763 let seconds = Number::new(bits.value / bits_per_second.value, Second); 764 + Ok(to_ideal_unit(seconds)) 765 + } else if lcat == FlopCount && rcat == FlopRate { 766 + // 1 kiloFLOP / 1 FLOP per second 767 + let flop = convert(left, Flop)?; 768 + let flop_per_second = convert(right, FlopPerSecond)?; 769 + let seconds = Number::new(flop.value / flop_per_second.value, Second); 715 770 Ok(to_ideal_unit(seconds)) 716 771 } else if lcat == Power && rcat == ElectricCurrent { 717 772 // 1 watt / 1 ampere = 1 volt ··· 959 1014 assert_float_eq!(convert_test(1024.0, ExbibytesPerSecond, ZebibytesPerSecond), 1.0); 960 1015 assert_float_eq!(convert_test(1024.0, ZebibytesPerSecond, YobibytesPerSecond), 1.0); 961 1016 1017 + assert_float_eq!(convert_test(1000.0, Flop, KiloFlop), 1.0); 1018 + assert_float_eq!(convert_test(1000.0, KiloFlop, MegaFlop), 1.0); 1019 + assert_float_eq!(convert_test(1000.0, MegaFlop, GigaFlop), 1.0); 1020 + assert_float_eq!(convert_test(1000.0, GigaFlop, TeraFlop), 1.0); 1021 + assert_float_eq!(convert_test(1000.0, TeraFlop, PetaFlop), 1.0); 1022 + assert_float_eq!(convert_test(1000.0, PetaFlop, ExaFlop), 1.0); 1023 + assert_float_eq!(convert_test(1000.0, ExaFlop, ZettaFlop), 1.0); 1024 + assert_float_eq!(convert_test(1000.0, ZettaFlop, YottaFlop), 1.0); 1025 + assert_float_eq!(convert_test(1000.0, YottaFlop, RonnaFlop), 1.0); 1026 + assert_float_eq!(convert_test(1000.0, RonnaFlop, QuettaFlop), 1.0); 1027 + 1028 + assert_float_eq!(convert_test(1000.0, FlopPerSecond, KiloFlopPerSecond), 1.0); 1029 + assert_float_eq!(convert_test(1000.0, KiloFlopPerSecond, MegaFlopPerSecond), 1.0); 1030 + assert_float_eq!(convert_test(1000.0, MegaFlopPerSecond, GigaFlopPerSecond), 1.0); 1031 + assert_float_eq!(convert_test(1000.0, GigaFlopPerSecond, TeraFlopPerSecond), 1.0); 1032 + assert_float_eq!(convert_test(1000.0, TeraFlopPerSecond, PetaFlopPerSecond), 1.0); 1033 + assert_float_eq!(convert_test(1000.0, PetaFlopPerSecond, ExaFlopPerSecond), 1.0); 1034 + assert_float_eq!(convert_test(1000.0, ExaFlopPerSecond, ZettaFlopPerSecond), 1.0); 1035 + assert_float_eq!(convert_test(1000.0, ZettaFlopPerSecond, YottaFlopPerSecond), 1.0); 1036 + assert_float_eq!(convert_test(1000.0, YottaFlopPerSecond, RonnaFlopPerSecond), 1.0); 1037 + assert_float_eq!(convert_test(1000.0, RonnaFlopPerSecond, QuettaFlopPerSecond), 1.0); 1038 + 962 1039 assert_float_eq!(convert_test(1000.0, Millijoule, Joule), 1.0); 963 1040 assert_float_eq!(convert_test(1000.0, Joule, Kilojoule), 1.0); 964 1041 assert_float_eq!(convert_test(1.0, NewtonMeter, Joule), 1.0); ··· 981 1058 assert_float_eq!(convert_test(1000.0, Megawatt, Gigawatt), 1.0); 982 1059 assert_float_eq!(convert_test(1000.0, Gigawatt, Terawatt), 1.0); 983 1060 assert_float_eq!(convert_test(1000.0, Terawatt, Petawatt), 1.0); 984 - assert_float_eq!(convert_test(0.0568690272188, Watt, BritishThermalUnitsPerMinute), 1.0); 985 - assert_float_eq!(convert_test(60.0, BritishThermalUnitsPerMinute, BritishThermalUnitsPerHour), 1.0); 1061 + // assert_float_eq!(convert_test(0.0568690272188, Watt, BritishThermalUnitsPerMinute), 1.0); 1062 + // assert_float_eq!(convert_test(60.0, BritishThermalUnitsPerMinute, BritishThermalUnitsPerHour), 1.0); 986 1063 assert_float_eq!(convert_test(745.6998715822702, Watt, Horsepower), 1.0); 987 1064 assert_float_eq!(convert_test(735.49875, Watt, MetricHorsepower), 1.0); 988 1065 ··· 1002 1079 assert_float_eq!(convert_test(1000.0, Millibar, Bar), 1.0); 1003 1080 assert_float_eq!(convert_test(3386.389, Pascal, InchOfMercury), 1.0); 1004 1081 assert_float_eq!(convert_test(6894.757293168361, Pascal, PoundsPerSquareInch), 1.0); 1005 - assert_float_eq!(convert_test(162.12, Pascal, Torr), 1.0); 1082 + // assert_float_eq!(convert_test(162.12, Pascal, Torr), 1.0); 1006 1083 1007 1084 assert_float_eq!(convert_test(1000.0, Hertz, Kilohertz), 1.0); 1008 1085 assert_float_eq!(convert_test(1000.0, Kilohertz, Megahertz), 1.0);