LCOV - code coverage report
Current view: top level - src - scs_parser.c (source / functions) Hit Total Coverage
Test: SuperSCS Unit Tests Lines: 280 282 99.3 %
Date: 2018-05-30 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * The MIT License (MIT)
       3             :  *
       4             :  * Copyright (c) 2017 Pantelis Sopasakis (https://alphaville.github.io),
       5             :  *                    Krina Menounou (https://www.linkedin.com/in/krinamenounou), 
       6             :  *                    Panagiotis Patrinos (http://homes.esat.kuleuven.be/~ppatrino)
       7             :  * Copyright (c) 2012 Brendan O'Donoghue (bodonoghue85@gmail.com)
       8             :  *
       9             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      10             :  * of this software and associated documentation files (the "Software"), to deal
      11             :  * in the Software without restriction, including without limitation the rights
      12             :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      13             :  * copies of the Software, and to permit persons to whom the Software is
      14             :  * furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included in all
      17             :  * copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      20             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      22             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      24             :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      25             :  * SOFTWARE.
      26             :  * 
      27             :  */
      28             : #include "scs_parser.h"
      29             : #include <stdio.h>
      30             : 
      31             : #if(defined _WIN32 || defined _WIN64 || defined _WINDLL)
      32             : #define SCS_FORMAT_ZU "%Iu"
      33             : #else
      34             : #define SCS_FORMAT_ZU "%zu"
      35             : #endif
      36             : 
      37             : static const char SCS_EOL = '\n';
      38             : #define SCS_YAML_CHAR_LEN 64
      39             : static const char scs_yaml_meta[] = "meta";
      40             : static const char scs_yaml_meta_id[] = "id";
      41             : static const char scs_yaml_meta_creator[] = "creator";
      42             : static const char scs_yaml_meta_license[] = "license";
      43             : static const char scs_yaml_meta_date[] = "date";
      44             : static const char scs_yaml_meta_yaml_version[] = "yamlVersion";
      45             : static const char scs_yaml_problem[] = "problem";
      46             : static const char scs_yaml_problem_name[] = "name";
      47             : static const char scs_yaml_m[] = "m";
      48             : static const char scs_yaml_n[] = "n";
      49             : static const char scs_yaml_nnz[] = "nnz";
      50             : static const char scs_yaml_matrix_A[] = "A";
      51             : static const char scs_yaml_matrix_A_a[] = "a";
      52             : static const char scs_yaml_matrix_A_I[] = "I";
      53             : static const char scs_yaml_matrix_A_J[] = "J";
      54             : static const char scs_yaml_vector_b[] = "b";
      55             : static const char scs_yaml_vector_c[] = "c";
      56             : static const char scs_yaml_cone_K[] = "K";
      57             : static const char scs_yaml_cone_field_ep[] = "ep";
      58             : static const char scs_yaml_cone_field_ed[] = "ed";
      59             : static const char scs_yaml_cone_field_f[] = "f";
      60             : static const char scs_yaml_cone_field_l[] = "l";
      61             : static const char scs_yaml_cone_field_p[] = "p";
      62             : static const char scs_yaml_cone_field_q[] = "q";
      63             : static const char scs_yaml_cone_field_s[] = "s";
      64             : static const char scs_yaml_cone_field_psize[] = "psize";
      65             : static const char scs_yaml_cone_field_qsize[] = "qsize";
      66             : static const char scs_yaml_cone_field_ssize[] = "ssize";
      67             : 
      68             : static char scs_yaml_variable_name[SCS_YAML_CHAR_LEN];
      69             : 
      70             : static void scs_yaml_clear_char_array(void) {
      71             :     memset(scs_yaml_variable_name, 0, SCS_YAML_CHAR_LEN * sizeof (char));
      72             : }
      73             : 
      74             : static void scs_yaml_skip_to_end_of_line(FILE * fp) {
      75             :     int c;
      76     3143046 :     while ((c = fgetc(fp)) != EOF && c != SCS_EOL);
      77             : }
      78             : 
      79        1560 : static char * scs_yaml_get_variable_name(FILE * fp) {
      80             :     int c;
      81        1560 :     size_t k = 0;
      82        1560 :     char colon = ':';
      83        1560 :     char hash = '#';
      84        1560 :     char begin_yaml[] = "---";
      85        1560 :     char end_yaml[] = "...";
      86             : 
      87             :     scs_yaml_clear_char_array();
      88             : 
      89             :     /* read the first three characters (unless a hash is found - then stop) */
      90       13430 :     while (k < 3 && (c = fgetc(fp)) != EOF && c != colon && c != hash)
      91       11870 :         if (c != ' ' && c != '\n') scs_yaml_variable_name[k++] = (char) c;
      92             : 
      93             :     /* check whether the first three chars are --- or ... */
      94        1560 :     if (strcmp(begin_yaml, scs_yaml_variable_name) == 0
      95        1510 :             || strcmp(end_yaml, scs_yaml_variable_name) == 0) {
      96             :         scs_yaml_skip_to_end_of_line(fp); /* skip to the end of the line */
      97             :         return SCS_NULL;
      98             :     }
      99             : 
     100        1460 :     if (c == hash) {
     101             :         scs_yaml_skip_to_end_of_line(fp); /* skip to the end of the line */
     102             :         return SCS_NULL;
     103             :     }
     104        1384 :     if (c == colon) return scs_yaml_variable_name;
     105             : 
     106             :     /* read the rest */
     107        1980 :     while ((c = fgetc(fp)) != EOF && c != colon)
     108        1438 :         if (c != ' ') scs_yaml_variable_name[k++] = (char) c;
     109             : 
     110             :     return scs_yaml_variable_name; /* variable name */
     111             : }
     112             : 
     113          50 : static void scs_yaml_skip_to_problem(FILE * fp) {
     114         474 :     while (!feof(fp)) {
     115             :         char * var_name;
     116         424 :         var_name = scs_yaml_get_variable_name(fp);
     117         424 :         if (var_name != SCS_NULL) {
     118             :             scs_yaml_skip_to_end_of_line(fp);
     119         350 :             if (strcmp(var_name, scs_yaml_problem) == 0) break;
     120             :         }
     121             :     }
     122          50 : }
     123             : 
     124         261 : static size_t scs_yaml_read_size_t(FILE * fp) {
     125             :     size_t value_in_yaml;
     126             :     int status;
     127         261 :     status = fscanf(fp, SCS_FORMAT_ZU, &value_in_yaml);
     128         261 :     if (status <= 0) value_in_yaml = 0;
     129         261 :     return value_in_yaml;
     130             : }
     131             : 
     132           1 : static scs_float scs_yaml_read_numeric(FILE * fp) {
     133             :     scs_float value_in_yaml;
     134             :     int status;
     135           1 :     status = fscanf(fp, "%lf", &value_in_yaml);
     136           1 :     if (status <= 0) value_in_yaml = 0;
     137           1 :     return value_in_yaml;
     138             : }
     139             : 
     140          25 : static void scs_yaml_discover_matrix_sizes(FILE * fp, ScsData * data, scs_int * nnz) {
     141             :     size_t k = 0;
     142         187 :     while (k++ < 6 && !feof(fp)) {
     143             :         char * var_name;
     144         162 :         var_name = scs_yaml_get_variable_name(fp);
     145         162 :         if (var_name == SCS_NULL) {
     146          12 :             k--;
     147          12 :             continue;
     148             :         }
     149         150 :         if (strcmp(var_name, scs_yaml_m) == 0) {
     150          25 :             data->m = scs_yaml_read_size_t(fp);
     151         125 :         } else if (strcmp(var_name, scs_yaml_n) == 0) {
     152          25 :             data->n = scs_yaml_read_size_t(fp);
     153         100 :         } else if (strcmp(var_name, scs_yaml_nnz) == 0) {
     154          25 :             *nnz = scs_yaml_read_size_t(fp);
     155             :         }
     156             :         scs_yaml_skip_to_end_of_line(fp);
     157             :     }
     158          25 : }
     159             : 
     160          25 : static void scs_yaml_discover_cone_sizes(FILE * fp, ScsCone * cone) {
     161          25 :     size_t k = 0;
     162         306 :     while (k++ < 10 && !feof(fp)) {
     163             :         char * var_name;
     164         256 :         var_name = scs_yaml_get_variable_name(fp);
     165         256 :         if (var_name == SCS_NULL) {
     166          12 :             k--;
     167          12 :             continue;
     168             :         }
     169         244 :         if (strcmp(var_name, scs_yaml_cone_field_psize) == 0) {
     170          23 :             cone->psize = scs_yaml_read_size_t(fp);
     171         221 :         } else if (strcmp(var_name, scs_yaml_cone_field_qsize) == 0) {
     172          25 :             cone->qsize = scs_yaml_read_size_t(fp);
     173         196 :         } else if (strcmp(var_name, scs_yaml_cone_field_ssize) == 0) {
     174          25 :             cone->ssize = scs_yaml_read_size_t(fp);
     175             :         }
     176             :         scs_yaml_skip_to_end_of_line(fp);
     177             :     }
     178          25 : }
     179             : 
     180          25 : static int scs_yaml_discover_sizes(
     181             :         FILE * fp,
     182             :         ScsData * data,
     183             :         ScsCone * cone,
     184             :         scs_int * nnz) {
     185          25 :     int checkpoints = 0;
     186             :     /* fast-forward to the problem */
     187          25 :     scs_yaml_skip_to_problem(fp);
     188             : 
     189             :     /* parse the problem */
     190         200 :     while (!feof(fp)) {
     191             :         char * variable_name;
     192         150 :         variable_name = scs_yaml_get_variable_name(fp);
     193             :         scs_yaml_skip_to_end_of_line(fp);
     194         150 :         if (variable_name == SCS_NULL) continue;
     195         123 :         if (strcmp(variable_name, scs_yaml_matrix_A) == 0) {
     196          25 :             checkpoints++;
     197          25 :             scs_yaml_discover_matrix_sizes(fp, data, nnz);
     198          98 :         } else if (strcmp(variable_name, scs_yaml_cone_K) == 0) {
     199          25 :             checkpoints++;
     200          25 :             scs_yaml_discover_cone_sizes(fp, cone);
     201             :         }
     202             :     }
     203          25 :     return checkpoints == 2 ? 0 : 1;
     204             : }
     205             : 
     206          25 : static int scs_yaml_initialise_data_and_cone(ScsData * data, ScsCone * cone, scs_int nnz) {
     207          25 :     if (data == SCS_NULL || cone == SCS_NULL) return 700;
     208          25 :     if (data->m <= 0) return 701;
     209          25 :     if (data->n <= 0) return 702;
     210          25 :     if (cone->psize < 0) return 703;
     211          25 :     if (cone->qsize < 0) return 704;
     212          25 :     if (cone->ssize < 0) return 705;
     213             : 
     214             :     /* initialise matrix `A` */
     215          25 :     data->A = scs_malloc(sizeof (ScsAMatrix));
     216          25 :     if (data->A == SCS_NULL) goto yaml_init_error_0;
     217          25 :     data->A->m = data->m;
     218          25 :     data->A->n = data->n;
     219          25 :     data->A->i = scs_malloc(nnz * sizeof (scs_int));
     220          25 :     if (data->A->i == SCS_NULL) goto yaml_init_error_1;
     221          25 :     data->A->p = scs_malloc((data->n + 1) * sizeof (scs_int));
     222          25 :     if (data->A->p == SCS_NULL) goto yaml_init_error_2;
     223          25 :     data->A->x = scs_malloc(nnz * sizeof (scs_float));
     224          25 :     if (data->A->x == SCS_NULL) goto yaml_init_error_3;
     225             : 
     226             :     /* initialise `b` and `c` */
     227          25 :     data->b = scs_malloc(data->m * sizeof (scs_float));
     228          25 :     if (data->b == SCS_NULL) goto yaml_init_error_4;
     229          25 :     data->c = scs_malloc(data->n * sizeof (scs_float));
     230          25 :     if (data->c == SCS_NULL) goto yaml_init_error_5;
     231             : 
     232             :     /* initialise `cone` */
     233          25 :     cone->p = scs_malloc(cone->psize * sizeof (scs_float));
     234          25 :     if (cone->psize > 0 && cone->p == SCS_NULL) goto yaml_init_error_6;
     235          25 :     cone->q = scs_malloc(cone->qsize * sizeof (scs_int));
     236          25 :     if (cone->qsize > 0 && cone->q == SCS_NULL) goto yaml_init_error_7;
     237          25 :     cone->s = scs_malloc(cone->ssize * sizeof (scs_int));
     238          25 :     if (cone->ssize && cone->s == SCS_NULL) goto yaml_init_error_8;
     239             : 
     240             :     return 0;
     241             : 
     242             :     /* LCOV_EXCL_START */
     243             : yaml_init_error_8:
     244             :     scs_free(cone->q);
     245             : yaml_init_error_7:
     246             :     scs_free(cone->p);
     247             : yaml_init_error_6:
     248             :     scs_free(data->c);
     249             : yaml_init_error_5:
     250             :     scs_free(data->b);
     251             : yaml_init_error_4:
     252             :     scs_free(data->A->x);
     253             : yaml_init_error_3:
     254             :     scs_free(data->A->p);
     255             : yaml_init_error_2:
     256             :     scs_free(data->A->i);
     257             : yaml_init_error_1:
     258             :     scs_free(data->A);
     259             : yaml_init_error_0:
     260             :     return 1;
     261             :     /* LCOV_EXCL_STOP */
     262             : }
     263             : 
     264          59 : static int scs_yaml_parse_int_array(FILE * fp, scs_int * array, size_t len) {
     265             :     int temp;
     266             :     size_t i;
     267          59 :     if (fscanf(fp, " [ %d", &temp) == 0) return 1;
     268          59 :     array[0] = temp;
     269      129612 :     for (i = 0; i < len - 1; ++i) {
     270      129553 :         if (fscanf(fp, " , %d", &temp) == 0) return 1;
     271      129553 :         array[i + 1] = temp;
     272             :     }
     273             :     return 0;
     274             : }
     275             : 
     276          78 : static int scs_yaml_parse_float_array(FILE * fp, scs_float * array, size_t len) {
     277             :     size_t i;
     278          78 :     if (fscanf(fp, " [ %lf ", array) == 0) return 1;
     279      173446 :     for (i = 0; i < len - 1; ++i)
     280      173368 :         if (fscanf(fp, " , %lf ", array + i + 1) == 0) return 1;
     281             :     return 0;
     282             : }
     283             : 
     284          25 : static int scs_yaml_parse_matrix_A(FILE * fp, ScsData * data, scs_int nonzeroes) {
     285             :     /* parse matrix A */
     286             :     size_t k = 0;
     287             :     int checkpoints = 0;
     288         187 :     while (k++ < 6 && !feof(fp)) {
     289             :         char * var_name;
     290         162 :         var_name = scs_yaml_get_variable_name(fp);
     291         162 :         if (var_name == SCS_NULL) {
     292          12 :             k--;
     293          12 :             continue;
     294             :         }
     295         150 :         if (strcmp(var_name, scs_yaml_matrix_A_I) == 0) {
     296          25 :             checkpoints++;
     297          25 :             if (scs_yaml_parse_int_array(fp, data->A->p, data->n + 1)) return 1;
     298         125 :         } else if (strcmp(var_name, scs_yaml_matrix_A_J) == 0) {
     299          25 :             checkpoints++;
     300          25 :             if (scs_yaml_parse_int_array(fp, data->A->i, nonzeroes)) return 1;
     301         100 :         } else if (strcmp(var_name, scs_yaml_matrix_A_a) == 0) {
     302          25 :             checkpoints++;
     303          25 :             if (scs_yaml_parse_float_array(fp, data->A->x, nonzeroes)) return 1;
     304             :         }
     305             :         scs_yaml_skip_to_end_of_line(fp);
     306             :     }
     307          25 :     return checkpoints == 3 ? 0 : 2;
     308             : }
     309             : 
     310          25 : static int scs_yaml_parse_cone_K(FILE * fp, ScsCone * cone) {
     311          25 :     size_t k = 0;
     312          25 :     char * var_name = SCS_NULL;
     313         306 :     while (k++ < 10 && !feof(fp)) {
     314         256 :         var_name = scs_yaml_get_variable_name(fp);
     315         256 :         if (var_name == SCS_NULL) {
     316          12 :             k--;
     317          12 :             continue;
     318             :         }
     319         244 :         if (strcmp(var_name, scs_yaml_cone_field_f) == 0) {
     320          23 :             cone->f = scs_yaml_read_size_t(fp);
     321         221 :         } else if (strcmp(var_name, scs_yaml_cone_field_l) == 0) {
     322          25 :             cone->l = scs_yaml_read_size_t(fp);
     323         196 :         } else if (strcmp(var_name, scs_yaml_cone_field_ep) == 0) {
     324          25 :             cone->ep = scs_yaml_read_size_t(fp);
     325         171 :         } else if (strcmp(var_name, scs_yaml_cone_field_ed) == 0) {
     326          23 :             cone->ed = scs_yaml_read_size_t(fp);
     327         148 :         } else if (strcmp(var_name, scs_yaml_cone_field_q) == 0) {
     328          25 :             if (cone->qsize == 1) {
     329          16 :                 cone->q[0] = (scs_int) scs_yaml_read_size_t(fp);
     330           9 :             } else if (cone->qsize > 1) {
     331           3 :                 if (scs_yaml_parse_int_array(fp, cone->q, cone->qsize)) return 1;
     332             :             }
     333         123 :         } else if (strcmp(var_name, scs_yaml_cone_field_p) == 0) {
     334          25 :             if (cone->psize == 1) {
     335           1 :                 cone->p[0] = scs_yaml_read_numeric(fp);
     336          24 :             } else if (cone->psize > 1) {
     337           3 :                 if (scs_yaml_parse_float_array(fp, cone->p, cone->psize)) return 1;
     338             :             }
     339          98 :         } else if (strcmp(var_name, scs_yaml_cone_field_s) == 0) {
     340          25 :             if (cone->ssize == 1) {
     341           1 :                 cone->s[0] = (scs_int) scs_yaml_read_size_t(fp);
     342          24 :             } else if (cone->ssize > 1) {
     343           6 :                 if (scs_yaml_parse_int_array(fp, cone->s, cone->ssize)) return 1;
     344             :             }
     345             :         }
     346             :         scs_yaml_skip_to_end_of_line(fp);
     347             :     }
     348             :     return 0;
     349             : }
     350             : 
     351          25 : static int scs_yaml_parse_data_and_cone(
     352             :         FILE * fp,
     353             :         ScsData * data,
     354             :         ScsCone * cone,
     355             :         scs_int nonzeroes) {
     356             :     /* fast-forward to the problem */
     357          25 :     scs_yaml_skip_to_problem(fp);
     358             : 
     359             :     /* parse the problem */
     360         200 :     while (!feof(fp)) {
     361         150 :         scs_yaml_get_variable_name(fp);
     362         150 :         if (strcmp(scs_yaml_variable_name, scs_yaml_matrix_A) == 0) {
     363             :             scs_yaml_skip_to_end_of_line(fp);
     364          25 :             if (scs_yaml_parse_matrix_A(fp, data, nonzeroes)) return 1;
     365         125 :         } else if (strcmp(scs_yaml_variable_name, scs_yaml_cone_K) == 0) {
     366             :             scs_yaml_skip_to_end_of_line(fp);
     367          25 :             if (scs_yaml_parse_cone_K(fp, cone)) return 1;
     368         100 :         } else if (strcmp(scs_yaml_variable_name, scs_yaml_vector_b) == 0) {
     369          25 :             if (scs_yaml_parse_float_array(fp, data->b, data->m)) return 1;
     370             :             scs_yaml_skip_to_end_of_line(fp);
     371          75 :         } else if (strcmp(scs_yaml_variable_name, scs_yaml_vector_c) == 0) {
     372          25 :             if (scs_yaml_parse_float_array(fp, data->c, data->n)) return 1;
     373             :             scs_yaml_skip_to_end_of_line(fp);
     374             :         } else {
     375             :             scs_yaml_skip_to_end_of_line(fp);
     376             :         }
     377             :     }
     378             :     return 0;
     379             : 
     380             : }
     381             : 
     382             : static void scs_reset_cone(ScsCone * cone) {
     383          25 :     cone->ssize = 0;
     384          25 :     cone->ed = 0;
     385          25 :     cone->ep = 0;
     386          25 :     cone->f = 0;
     387          25 :     cone->l = 0;
     388          25 :     cone->psize = 0;
     389             :     cone->ssize = 0;
     390          25 :     cone->qsize = 0;
     391          25 :     cone->q = SCS_NULL;
     392          25 :     cone->p = SCS_NULL;
     393          25 :     cone->s = SCS_NULL;
     394             : }
     395             : 
     396          25 : scs_int scs_from_YAML(
     397             :         const char * filepath,
     398             :         ScsData ** data,
     399             :         ScsCone ** cone) {
     400             : 
     401          25 :     FILE *fp = SCS_NULL;
     402             :     scs_int status;
     403             :     scs_int nonzeroes;
     404             : 
     405          25 :     nonzeroes = 0;
     406          25 :     status = 0;
     407             : 
     408          25 :     *data = scs_init_data();
     409          25 :     if (data == SCS_NULL) {
     410             :         status = 501;
     411             :         goto exit_error_1;
     412             :     }
     413             : 
     414          25 :     *cone = scs_malloc(sizeof (ScsCone));
     415          25 :     scs_reset_cone(*cone);
     416          25 :     if (cone == SCS_NULL) {
     417             :         status = 502;
     418             :         goto exit_error_2;
     419             :     }
     420             : 
     421          25 :     fp = fopen(filepath, "r");
     422             : 
     423          25 :     if (fp == NULL) {
     424             :         status = 1000;
     425             :         goto exit_error_2;
     426             :     }
     427             : 
     428             : 
     429             :     /* first we need to know the sizes */
     430          25 :     if (scs_yaml_discover_sizes(fp, *data, *cone, &nonzeroes)) {
     431             :         status = 101;
     432             :         goto exit_error_2;
     433             :     }
     434             : 
     435             :     /* we know the dimensions - initialise `data` and `cone` */
     436          25 :     if ((status = scs_yaml_initialise_data_and_cone(*data, *cone, nonzeroes)))
     437             :         goto exit_error_2;
     438             : 
     439             :     /* rewind file */
     440          25 :     rewind(fp);
     441             : 
     442             :     /* parse `data` and `cone` */
     443          25 :     if (scs_yaml_parse_data_and_cone(fp, *data, *cone, nonzeroes)) {
     444             :         status = 103;
     445             :         goto exit_error_2;
     446             :     }
     447             : 
     448          25 :     if (fp != SCS_NULL) {
     449          25 :         if (0 != fclose(fp)) {
     450           0 :             status = 224;
     451             :         }
     452             :     }
     453          25 :     return status;
     454             : 
     455             :     /* LCOV_EXCL_START */
     456             : exit_error_2:
     457             :     scs_free_data_cone(*data, *cone);
     458             : exit_error_1:
     459             :     if (fp != SCS_NULL)
     460             :         fclose(fp);
     461             :     return status;
     462             :     /* LCOV_EXCL_STOP */
     463             : }
     464             : 
     465             : static int scs_double_num_digits = 17;
     466             : static char scs_yaml_space[] = "    ";
     467             : static char scs_yaml_double_space[] = "        ";
     468             : 
     469          64 : static void scs_serialize_array_to_YAML(
     470             :         FILE * RESTRICT fp,
     471             :         void * array,
     472             :         scs_int len,
     473             :         scs_int is_array_int
     474             :         ) {
     475             :     fprintf(fp, "[");
     476          64 :     if (len > 0) {
     477             :         size_t i;
     478          49 :         if (is_array_int) {
     479             :             scs_int * int_array = (scs_int *) array;
     480        9859 :             for (i = 0; i < len - 1; ++i) {
     481        9859 :                 fprintf(fp, "%d,", (int) int_array[i]);
     482             :             }
     483          21 :             fprintf(fp, "%d", (int) int_array[len - 1]);
     484             :         } else {
     485             :             scs_float * float_array = (scs_float *) array;
     486       11132 :             for (i = 0; i < len - 1; ++i) {
     487       11132 :                 fprintf(fp, "%.*g,", scs_double_num_digits, (double) float_array[i]);
     488             :             }
     489          28 :             fprintf(fp, "%.*g", scs_double_num_digits, (double) float_array[len - 1]);
     490             :         }
     491             :     }
     492             :     fprintf(fp, "]\n");
     493          64 : }
     494             : 
     495           9 : static void scs_serialize_sparse_matrix_to_YAML(
     496             :         FILE * RESTRICT fp,
     497             :         const ScsAMatrix * RESTRICT matrix) {
     498           9 :     scs_int num_nonzeroes = matrix->p[matrix->n];
     499             :     fprintf(fp, "%s%s:\n", scs_yaml_space, scs_yaml_matrix_A);
     500           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_m, (int) matrix->m);
     501           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_n, (int) matrix->n);
     502             :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_nnz, (int) num_nonzeroes);
     503             :     fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_matrix_A_a);
     504           9 :     scs_serialize_array_to_YAML(fp, matrix->x, num_nonzeroes, 0);
     505             :     fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_matrix_A_I);
     506           9 :     scs_serialize_array_to_YAML(fp, matrix->p, matrix->n + 1, 1);
     507             :     fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_matrix_A_J);
     508           9 :     scs_serialize_array_to_YAML(fp, matrix->i, num_nonzeroes, 1);
     509           9 : }
     510             : 
     511           9 : static void scs_serialize_vectors_to_YAML(
     512             :         FILE * RESTRICT fp,
     513             :         const ScsData * RESTRICT data) {
     514             :     fprintf(fp, "%s%s: ", scs_yaml_space, scs_yaml_vector_b);
     515           9 :     scs_serialize_array_to_YAML(fp, data->b, data->m, 0);
     516             :     fprintf(fp, "%s%s: ", scs_yaml_space, scs_yaml_vector_c);
     517           9 :     scs_serialize_array_to_YAML(fp, data->c, data->n, 0);
     518           9 : }
     519             : 
     520           9 : static void scs_serialize_cone_to_YAML(
     521             :         FILE * RESTRICT fp,
     522             :         const ScsCone * RESTRICT cone) {
     523             :     fprintf(fp, "%s%s:\n", scs_yaml_space, scs_yaml_cone_K);
     524           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_psize, (int) cone->psize);
     525           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_qsize, (int) cone->qsize);
     526           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_ssize, (int) cone->ssize);
     527           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_f, (int) cone->f);
     528           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_l, (int) cone->l);
     529           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_ep, (int) cone->ep);
     530           9 :     fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_ed, (int) cone->ed);
     531           9 :     if (cone->qsize == 1) {
     532           6 :         fprintf(fp, "%s%s: %d\n", scs_yaml_double_space, scs_yaml_cone_field_q, (int) cone->q[0]);
     533             :     } else {
     534             :         fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_cone_field_q);
     535           3 :         scs_serialize_array_to_YAML(fp, cone->q, cone->qsize, 1);
     536             :     }
     537           9 :     if (cone->psize == 1) {
     538           1 :         fprintf(fp, "%s%s: %.*g\n", scs_yaml_double_space,
     539             :                 scs_yaml_cone_field_p, scs_double_num_digits,
     540           1 :                 (double) cone->p[0]);
     541             :     } else {
     542             :         fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_cone_field_p);
     543           8 :         scs_serialize_array_to_YAML(fp, cone->p, cone->psize, 0);
     544             :     }
     545           9 :     if (cone->ssize == 1) {
     546           1 :         fprintf(fp, "%s%s: %d\n", scs_yaml_double_space,
     547           1 :                 scs_yaml_cone_field_s, (int) cone->s[0]);
     548             :     } else {
     549             :         fprintf(fp, "%s%s: ", scs_yaml_double_space, scs_yaml_cone_field_s);
     550           8 :         scs_serialize_array_to_YAML(fp, cone->s, cone->ssize, 1);
     551             :     }
     552           9 : }
     553             : 
     554           9 : scs_int scs_to_YAML(
     555             :         const char * RESTRICT filepath,
     556             :         ScsConicProblemMetadata * metadata,
     557             :         const ScsData * RESTRICT data,
     558             :         const ScsCone * RESTRICT cone) {
     559           9 :     scs_int status = 0;
     560           9 :     FILE *fp = SCS_NULL;
     561           9 :     scs_int should_free_metadata = 0;
     562             : 
     563           9 :     if (data == SCS_NULL) return 501;
     564           9 :     if (cone == SCS_NULL) return 502;
     565           9 :     if (filepath == SCS_NULL) return 503;
     566             : 
     567           9 :     if (metadata == SCS_NULL) {
     568           1 :         metadata = scs_init_conic_problem_metadata("anonymous-conic-problem");
     569           1 :         if (metadata == SCS_NULL) return 600;
     570             :         should_free_metadata = 1;
     571             :     }
     572             : 
     573           9 :     fp = fopen(filepath, "w");
     574             : 
     575           9 :     if (fp == NULL) {
     576             :         status = 101;
     577             :         goto to_yaml_exit_0;
     578             :     }
     579             :     fprintf(fp, "--- # SuperSCS Problem\n%s:\n", scs_yaml_meta);
     580           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_meta_id, metadata->id);
     581           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_meta_creator, metadata->creator);
     582           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_meta_yaml_version, metadata->yamlVersion);
     583           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_meta_license, metadata->license);
     584           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_meta_date, metadata->date);
     585             :     fprintf(fp, "%s:\n", scs_yaml_problem);
     586           9 :     fprintf(fp, "%s%s: '%s'\n", scs_yaml_space, scs_yaml_problem_name, metadata->problemName);
     587           9 :     scs_serialize_sparse_matrix_to_YAML(fp, data->A);
     588           9 :     scs_serialize_vectors_to_YAML(fp, data);
     589           9 :     scs_serialize_cone_to_YAML(fp, cone);
     590             :     fprintf(fp, "...");
     591             : 
     592             : to_yaml_exit_0:
     593           9 :     if (fp != SCS_NULL) {
     594           9 :         if (fclose(fp) != 0) {
     595           0 :             status = 250;
     596             :         }
     597             :     }
     598           9 :     if (should_free_metadata) {
     599           1 :         scs_free(metadata);
     600             :     }
     601           9 :     return status;
     602             : }
     603             : 
     604           4 : static int scs_time_offset(void) {
     605           4 :     time_t gmt, rawtime = time(NULL);
     606             :     struct tm *ptm;
     607             : #if !defined(WIN32)
     608             :     struct tm gbuf;
     609           4 :     ptm = gmtime_r(&rawtime, &gbuf);
     610             : #else
     611             :     ptm = gmtime(&rawtime);
     612             : #endif
     613             :     // Request that mktime() looksup dst in timezone database
     614           4 :     ptm->tm_isdst = -1;
     615           4 :     gmt = mktime(ptm);
     616           4 :     return (int) difftime(rawtime, gmt) / 3600;
     617             : }
     618             : 
     619           4 : ScsConicProblemMetadata * scs_init_conic_problem_metadata(const char * problemName) {
     620           4 :     ScsConicProblemMetadata * metadata = SCS_NULL;
     621           4 :     time_t t = time(NULL);
     622           4 :     struct tm date_time_now = *localtime(&t);
     623             : 
     624           4 :     metadata = scs_malloc(sizeof (*metadata));
     625           4 :     if (metadata == SCS_NULL) return SCS_NULL;
     626           4 :     strncpy(metadata->license,
     627             :             "https://github.com/kul-forbes/scs/blob/master/LICENSE.txt",
     628             :             SCS_METADATA_TEXT_SIZE);
     629           4 :     strncpy(metadata->problemName, problemName, SCS_METADATA_TEXT_SIZE);
     630           4 :     snprintf(metadata->id, SCS_METADATA_TEXT_SIZE, "http://superscs.org/problem/%s", problemName);
     631           4 :     snprintf(metadata->creator, SCS_METADATA_TEXT_SIZE, "%s", scs_version());
     632           4 :     snprintf(metadata->date, SCS_METADATA_TEXT_SIZE,
     633             :             "%d-%d-%d %d:%d:%d [GMT+%d]",
     634             :             date_time_now.tm_year + 1900,
     635             :             date_time_now.tm_mon + 1,
     636             :             date_time_now.tm_mday,
     637             :             date_time_now.tm_hour,
     638             :             date_time_now.tm_min,
     639             :             date_time_now.tm_sec,
     640             :             scs_time_offset());
     641             : 
     642           4 :     snprintf(metadata->yamlVersion, SCS_METADATA_TEXT_SIZE, "1.2");
     643           4 :     return metadata;
     644             : }

Generated by: LCOV version 1.10