Advertisement
diaaa

Untitled

Feb 23rd, 2022
1,294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Latex 11.91 KB | None | 0 0
  1. \begin{filecontents*}{test.csv}
  2.     First ,   4 , 0 ,  2 , 5
  3.     Second ,  0 , 0 ,  7 , 8
  4.     Third ,   5 , 0 ,  6 ,
  5.     Fourth , -5 , 0 , -6 ,
  6. \end{filecontents*}
  7.  
  8.  
  9. \documentclass{article}
  10.  
  11. \ExplSyntaxOn
  12. % Step 1: reading the file
  13. \tl_new:N \l__diaa_tmpa_tl
  14. \ior_new:N \l__diaa_csv_ior
  15. \bool_new:N \l__diaa_csv_str_bool
  16. \bool_new:N \l__diaa_empty_item_bool
  17. \seq_new:N \l__diaa_csv_tmp_seq
  18.  
  19. % str mode (bool/star), key column, label, value columns, file
  20. \NewDocumentCommand \ReadCSV { s O{1} m O{} m }
  21. {
  22.     \IfBooleanTF {#1}
  23.     { \bool_set_true:N \l__diaa_csv_str_bool }
  24.     { \bool_set_false:N \l__diaa_csv_str_bool }
  25.     \diaa_csv_read:nnnn {#3} {#2} {#4} {#5}
  26. }
  27.  
  28. % label, key column, value columns, file
  29. \cs_new_protected:Npn \diaa_csv_read:nnnn #1 #2 #3 #4
  30. {
  31.     \tl_if_blank:nTF {#3}       % Detect number of columns and use 2 to last
  32.     {
  33.         \ior_open:NnTF \l__diaa_csv_ior {#4}
  34.         {
  35.             \bool_if:NTF \l__diaa_csv_str_bool
  36.             { \ior_str_get:NN }
  37.             { \ior_get:NN }
  38.             \l__diaa_csv_ior \l__diaa_tmpa_tl
  39.            
  40.             \ior_close:N \l__diaa_csv_ior
  41.             \seq_set_split:NnV \l_tmpa_seq { , } \l__diaa_tmpa_tl
  42.             \seq_clear:N \l__diaa_csv_tmp_seq
  43.             \int_step_inline:nnn { 2 } { \seq_count:N \l_tmpa_seq }
  44.             { \seq_put_right:Nn \l__diaa_csv_tmp_seq {##1} }
  45.         }
  46.         { \msg_expandable_error:nnn { diaa } { file-not-found } {#4} }
  47.     }
  48.     { \seq_set_split:Nnn \l__diaa_csv_tmp_seq { , } {#3} } % explicit columns
  49.    
  50.     \ior_open:NnTF \l__diaa_csv_ior {#4}
  51.     {
  52.         \prop_new:c { g__diaa_csv_#1_prop }
  53.         \__diaa_csv_read:nn {#1} {#2}
  54.         \ior_close:N \l__diaa_csv_ior
  55.     }
  56.     { \msg_expandable_error:nnn { diaa } { file-not-found } {#4} }
  57. }
  58.  
  59. \msg_new:nnn { diaa } { file-not-found }
  60. { File~`#1'~not~found. }
  61.  
  62. \cs_generate_variant:Nn \prop_put:Nnn { cxV }
  63.  
  64. % label, key column
  65. \cs_new_protected:Npn \__diaa_csv_read:nn #1 #2
  66. {
  67.     \bool_if:NTF \l__diaa_csv_str_bool
  68.     { \ior_str_map_inline:Nn }
  69.     { \ior_map_inline:Nn }
  70.     \l__diaa_csv_ior
  71.     {
  72.         \seq_set_split:Nnn \l_tmpa_seq { , } {##1} % split one CSV row
  73.         \tl_clear:N \l__diaa_tmpa_tl
  74.         \seq_map_inline:Nn \l__diaa_csv_tmp_seq
  75.         {
  76.             \tl_put_right:Nx \l__diaa_tmpa_tl { { \seq_item:Nn \l_tmpa_seq {####1} } }
  77.         }
  78.         \prop_put:cxV { g__diaa_csv_#1_prop }
  79.         { \seq_item:Nn \l_tmpa_seq {#2} }
  80.         \l__diaa_tmpa_tl
  81.     }
  82. }
  83.  
  84. %%%%%%%%%%%%%%%%%%%%%%%%
  85.  
  86. % https://tex.stackexchange.com/a/634894/2288
  87.  
  88. \keys_define:nn { diaa / getPolyFromRow }
  89. {
  90.     global-assignment .bool_set:N = \l__diaa_gpfr_global_assignment_bool,
  91.     global-assignment .default:n = true,
  92.     global-assignment .initial:n = false,
  93.     variable .tl_set:N = \l__diaa_gpfr_variable_name_tl,
  94.     variable .value_required:n = true,
  95.     variable .initial:n = X,
  96.     typographical-variant .str_set:N = \l__diaa_gpfr_typographical_variant_str,
  97.     typographical-variant .value_required:n = true,
  98.     typographical-variant .initial:n = default,
  99. }
  100.  
  101. % \getPolyFromRow will temporarily store the result in this variable. This
  102. % allows us not to lose the result when the group started for \keys_set:nn
  103. % ends (if the user chose to perform a local assignment, this must be done
  104. % after closing that group).
  105. \tl_new:N \g__diaa_gpfr_result_tl
  106.  
  107.  
  108. % Options, macro for result, key, datafile label
  109. \NewDocumentCommand \getPolyFromRow { O{} m m m }
  110. {
  111.     \group_begin:
  112.     \keys_set:nn { diaa / getPolyFromRow } {#1}
  113.    
  114.     % Globally define _gfunc function aliases that perform global or local
  115.     % assignments depending on \l__diaa_gpfr_global_assignment_bool. They
  116.     % will be used *after* we close the current group.
  117.     \bool_set_true:N \l__diaa_gpfr_dtfa_global_aliases_bool
  118.     \__diaa_gpfr_define_tl_func_aliases:
  119.    
  120.     % Store the result in \g__diaa_gpfr_result_tl for now.
  121.     \bool_set_true:N \l__diaa_gpfr_global_assignment_bool
  122.     \diaa_get_poly_from_row:Nnn \g__diaa_gpfr_result_tl {#3} {#4}
  123.     \group_end:
  124.    
  125.     % Use the globally-defined aliases to perform the user-chosen (local or
  126.     % global) kind of assignment.
  127.     \__diaa_clear_gfunc:N #2    % make sure the tl var #2 is defined
  128.     \__diaa_set_eq_gfunc:NN #2 \g__diaa_gpfr_result_tl % set it
  129. }
  130.  
  131. % True to globally define the aliases and give them _gfunc names rather than
  132. % _func
  133. \bool_new:N \l__diaa_gpfr_dtfa_global_aliases_bool
  134.  
  135. \cs_new_protected:Npn \__diaa_gpfr_define_tl_func_aliases:
  136. {
  137.     \bool_if:NTF \l__diaa_gpfr_global_assignment_bool
  138.     {
  139.         \__diaa_gpfr_define_alias:nnN { clear }     { N }  \tl_gclear_new:N
  140.         \__diaa_gpfr_define_alias:nnN { set_eq }    { NN } \tl_gset_eq:NN
  141.         \__diaa_gpfr_define_alias:nnN { put_right } { Nn } \tl_gput_right:Nn
  142.     }
  143.     {
  144.         \__diaa_gpfr_define_alias:nnN { clear }     { N }  \tl_clear_new:N
  145.         \__diaa_gpfr_define_alias:nnN { set_eq }    { NN } \tl_set_eq:NN
  146.         \__diaa_gpfr_define_alias:nnN { put_right } { Nn } \tl_put_right:Nn
  147.     }
  148. }
  149.  
  150. % Locally or globally define an alias for a function. The alias is defined
  151. % globally with a gfunc name if \l__diaa_gpfr_dtfa_global_aliases_bool is true.
  152. %
  153. % #1: stem such as “clear”, “put_right”, etc.
  154. % #2: signature of the alias (e.g., “Nn”)
  155. \cs_new_protected:Npn \__diaa_gpfr_define_alias:nnN #1#2
  156. {
  157.     \bool_if:NTF \l__diaa_gpfr_dtfa_global_aliases_bool
  158.     { \cs_gset_eq:cN }
  159.     { \cs_set_eq:cN }
  160.     {
  161.         __diaa_#1_
  162.         \bool_if:NT \l__diaa_gpfr_dtfa_global_aliases_bool { g }
  163.         func:#2
  164.     }
  165. }
  166.  
  167. \int_new:N \l__diaa_gpfr_degree_int
  168. \cs_generate_variant:Nn \__diaa_put_right_func:Nn { Nx }
  169. \cs_generate_variant:Nn \__diaa_get_poly_from_row_append_monomial:Nnn { NnV }
  170.  
  171. % Macro for result, key, datafile label
  172. \cs_new_protected:Npn \diaa_get_poly_from_row:Nnn #1#2#3
  173. {
  174.     % Locally define function aliases that perform global or local assignments
  175.     % depending on \l__diaa_gpfr_global_assignment_bool: \__diaa_clear_func:Nn,
  176.     % \__diaa_put_right_func:Nn, etc.
  177.     \bool_set_false:N \l__diaa_gpfr_dtfa_global_aliases_bool
  178.     \__diaa_gpfr_define_tl_func_aliases:
  179.    
  180.     \prop_get:cnN { g__diaa_csv_#3_prop } {#2} \l__diaa_tmpa_tl % the coefficients
  181.    
  182.     % Let's put (1 + degree) for now in this int variable.
  183.     \int_zero:N \l__diaa_gpfr_degree_int
  184.     \tl_map_inline:Nn \l__diaa_tmpa_tl
  185.     {
  186.         \tl_if_empty:nT {##1} { \tl_map_break: }
  187.         \int_incr:N \l__diaa_gpfr_degree_int
  188.     }
  189.    
  190.     \__diaa_clear_func:N #1        % initialize #1 as a tl var if necessary
  191.     \bool_set_false:N \l_tmpa_bool % true: add + operator if next coeff is > 0
  192.    
  193.     \tl_map_inline:Nn \l__diaa_tmpa_tl % loop over the coefficients
  194.     {
  195.         % Degree of the monomial we're about to output
  196.         \int_decr:N \l__diaa_gpfr_degree_int
  197.         % Early termination condition if the row is not full of coefficients
  198.         \int_compare:nNnT { \l__diaa_gpfr_degree_int } < { 0 }
  199.         { \tl_map_break: }
  200.        
  201.         \fp_compare:nNnF {##1} = { 0 }
  202.         {
  203.             % Insert a + operator if necessary
  204.             \bool_if:NTF \l_tmpa_bool
  205.             {
  206.                 \fp_compare:nNnT {##1} > { 0 }
  207.                 { \__diaa_put_right_func:Nn #1 { + } }
  208.             }
  209.             { \bool_set_true:N \l_tmpa_bool }
  210.            
  211.             % Insert the monomial
  212.             \__diaa_get_poly_from_row_append_monomial:NnV #1 {##1}
  213.             \l__diaa_gpfr_variable_name_tl
  214.         }
  215.     }
  216. }
  217.  
  218. \msg_new:nnn { diaa } { gpfr-unknown-typo-variant }
  219. { Unknown~typographical~variant~for~\token_to_str:N \getPolyFromRow :~`#1'. }
  220.  
  221. \cs_generate_variant:Nn \str_case_e:nnF { V }
  222. \cs_generate_variant:Nn \msg_error:nnn { nnV }
  223.  
  224. % Macro, coefficient, variable name
  225. \cs_new_protected:Npn \__diaa_get_poly_from_row_append_monomial:Nnn #1#2#3
  226. {
  227.     \str_case_e:VnF \l__diaa_gpfr_typographical_variant_str
  228.     {
  229.         { default }     { \tl_set:Nn \l__diaa_tmpa_tl { #2 \times #3 ^ } }
  230.         { with-braces } { \tl_set:Nn \l__diaa_tmpa_tl { #2 \times {#3} ^ } }
  231.     }
  232.     {
  233.         \msg_error:nnV { diaa } { gpfr-unknown-typo-variant }
  234.         \l__diaa_gpfr_typographical_variant_str
  235.     }
  236.    
  237.     \__diaa_put_right_func:Nx #1
  238.     {
  239.         \int_case:nnF { \l__diaa_gpfr_degree_int } % depending on the degree...
  240.         {
  241.             { 0 } { \exp_not:n {#2} } % degree 0 → only the coefficient
  242.             { 1 } { \exp_not:n { #2 \times #3 } }
  243.         }
  244.         { % Other degrees
  245.             \exp_not:V \l__diaa_tmpa_tl % use the selected variant
  246.             % Use braces in case the exponent has several digits
  247.             { \int_use:N \l__diaa_gpfr_degree_int }
  248.         }
  249.     }
  250. }
  251.  
  252. %%%%%%%%%%%%%%%%%%%%%
  253.  
  254. % Step 2: getting the values
  255. % star → global assignment, macro or tl var, value column, key, label
  256. \NewDocumentCommand \getValue { s m O{1} m m }
  257. {
  258.     \IfBooleanTF {#1} { \tl_gset:Nx } { \tl_set:Nx }
  259.     #2 { \diaa_csv_item:nnn {#4} {#3} {#5} }
  260.     \tl_if_empty:NT #2
  261.     { \msg_warning:nnnnn { diaa } { item-empty } {#3} {#4} {#5} }
  262. }
  263.  
  264. % key, value column, label
  265. \NewExpandableDocumentCommand \CSVItem { m O{1} m }
  266. { \diaa_csv_item:nnn {#1} {#2} {#3} }
  267.  
  268. % Version with error if empty
  269. % \NewExpandableDocumentCommand \CSVItem { m O{1} m }
  270. %   {
  271.     %     \exp_args:Nf \__diaa_check_empty_item:nnnn
  272.     %       { \diaa_csv_item:nnn {#1} {#2} {#3} } {#2} {#1} {#3}
  273.     %   }
  274. % \cs_new:Npn \__diaa_check_empty_item:nnnn #1 #2 #3 #4
  275. %   {
  276.     %     \tl_if_empty:nTF {#1}
  277.     %       { \msg_expandable_error:nnnnn { diaa } { item-empty } {#2} {#3} {#4} }
  278.     %       {#1}
  279.     %   }
  280.  
  281. \cs_generate_variant:Nn \tl_item:nn { f }
  282.  
  283. % key, value column, label
  284. \cs_new:Npn \diaa_csv_item:nnn #1 #2 #3
  285. {
  286.     \prop_if_exist:cTF { g__diaa_csv_#3_prop }
  287.     {
  288.         \prop_if_in:cnTF { g__diaa_csv_#3_prop } {#1}
  289.         {
  290.             \exp_args:NNf \__diaa_check_column_range:Nnn \use_i:nn
  291.             { \prop_item:cn { g__diaa_csv_#3_prop } {#1} } {#2}
  292.         }
  293.         { \msg_expandable_error:nnnn { diaa } { key-undefined } {#1} {#3} }
  294.     }
  295.     { \msg_expandable_error:nnn { diaa } { csv-undefined } {#3} }
  296. }
  297.  
  298. \cs_new:Npn \__diaa_check_column_range:Nnn #1 #2 #3
  299. {
  300.     \bool_lazy_or:nnTF
  301.     { \int_compare_p:nNn {#3} = { 0 } }
  302.     { \int_compare_p:nNn { \tl_count:n {#2} } < { \int_abs:n {#3} } }
  303.     { \msg_expandable_error:nnn { diaa } { out-of-range } {#3} }
  304.     { \exp_args:Nf #1 { \tl_item:nn {#2} {#3} } {#3} }
  305. }
  306.  
  307. \msg_new:nnn { diaa } { csv-undefined } { CSV~database~''#1''~is~undefined! }
  308. \msg_new:nnn { diaa } { key-undefined } {Parameter~''#1''~is~not~found~in~CSV~''#2''! }
  309. \msg_new:nnn { diaa } { out-of-range } { Column~#1~is~out~of~range! }
  310. %\msg_new:nnn { diaa } { item-empty }
  311. %{ Column~#1~of~''#2''~in~CSV~''#3''~is~empty! }
  312. \msg_new:nnn { diaa } { item-empty }
  313. { Empty~column~#1~of~''#2''~in~CSV~''#3''! }%Item~#1~from~`#2'~in~CSV~`#3'~is~empty!
  314. \msg_new:nnn { diaa } { empty-row-item }
  315. { Empty~item~#1~\msg_line_context:! }
  316. \msg_new:nnn { diaa } { row-empty }
  317. { Empty~parameter~''#1''~in~CSV~''#2''! }
  318.  
  319.  
  320. \cs_new:Npn \__diaa_check_empty:nn #1 #2
  321. {
  322.     \tl_if_empty:nT {#1}
  323.     { \msg_warning:nnn { diaa } { empty-row-item } {#2} }
  324.     #1
  325. }
  326.  
  327. % star → global assignment, macro, key, label
  328. \NewDocumentCommand \getRow { s m m m }
  329. {
  330.     \prop_if_exist:cTF { g__diaa_csv_#4_prop }
  331.     {
  332.         \prop_get:cnNTF { g__diaa_csv_#4_prop } {#3} \l__diaa_tmpa_tl
  333.         {
  334.             \bool_set_true:N \l__diaa_empty_item_bool
  335.             \tl_map_inline:Nn \l__diaa_tmpa_tl
  336.             {
  337.                 \tl_if_empty:nF {##1}
  338.                 { \bool_set_false:N \l__diaa_empty_item_bool }
  339.             }
  340.             \bool_if:NT \l__diaa_empty_item_bool
  341.             { \msg_warning:nnnn { diaa } { row-empty } {#3} {#4} }
  342.             \IfBooleanTF {#1} { \cs_gset_nopar:Npx } { \cs_set_nopar:Npx } #2 [ ##1 ]
  343.             {
  344.                 \exp_not:N \str_if_eq:nnTF {##1} { non-empty }
  345.                 {
  346.                     \exp_not:N \__diaa_nb_nonempty_items_in_row:nw { 0 }
  347.                     \exp_not:V \l__diaa_tmpa_tl
  348.                     \exp_not:n { \q_recursion_tail \q_recursion_stop }
  349.                 }
  350.                 {
  351.                     \exp_not:N \__diaa_check_column_range:Nnn
  352.                     \exp_not:N \__diaa_check_empty:nn
  353.                     { \exp_not:V \l__diaa_tmpa_tl } {##1}
  354.                 }
  355.             }
  356.         }
  357.         { \msg_expandable_error:nnnn { diaa } { key-undefined } {#3} {#4} }
  358.     }
  359.     { \msg_expandable_error:nnn { diaa } { csv-undefined } {#4} }
  360. }
  361.  
  362.  
  363. \cs_new:Npn \__diaa_nb_nonempty_items_in_row:nw #1#2
  364. {
  365.     \quark_if_recursion_tail_stop_do:nn {#2} { \int_eval:n {#1} }
  366.     \tl_if_empty:nTF {#2}
  367.     { \__diaa_nb_nonempty_items_in_row:nw {#1} }
  368.     { \__diaa_nb_nonempty_items_in_row:nw { #1 + 1 } }
  369. }
  370. \ExplSyntaxOff
  371.  
  372.  
  373. \begin{document}
  374.     \getPolyFromRow{\firstPoly}{First}{mydata}%
  375.     The first polynom is $\firstPoly$.
  376.    
  377.     \getPolyFromRow[variable=v]{\secondPoly}{Second}{mydata}%
  378.     The second polynom is $\secondPoly$.
  379.    
  380.     \getValue\First{First}{mydata}
  381.     \First
  382.    
  383.     \getRow{\RowThird}{Third}{mydata}
  384.     \RowThird
  385. \end{document}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement