summaryrefslogtreecommitdiff
path: root/sci_gateway/cpp/sci_sym_get_matrix.cpp
blob: 8b8f62011dc720b6a11238389ccdcf4db54f1aea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright (C) 2015 - IIT Bombay - FOSSEE
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution.  The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
// Author: Sai Kiran
// Organization: FOSSEE, IIT Bombay
// Email: toolbox@scilab.in

#include <symphony.h>
#include <sci_iofunc.hpp>
extern sym_environment* global_sym_env;//defined in globals.cpp

extern "C" {
#include <api_scilab.h>
#include <Scierror.h>
#include <BOOL.h>
#include <stdlib.h>
#include <malloc.h>
#include <localization.h>
#include <sciprint.h>

#include <string.h>

/*
 * Proto-type of function that converts column-major (sparse) representation
 * to row-major (sparse) representation .
*/
void column_major_to_row_major(int,int,int,double *,int *,int *,double *,int *,int *);


/* This function is to retrieve the problem's constraint matrix (sparse) .
 * Symphony uses column-major (sparse) representation.
 * Scilab uses row-major (sparse) representation.
 * So, This function takes column-major (sparse) representation from symphony ,
 * converts that to row-major (sparse) representation and writes to scilab's memory.
 *
 **/
int sci_sym_get_matrix(char *fname, unsigned long fname_len){
	int nz_ele=0;// No.of non-zero elements of the matrix
	int rows=0; //No. of rows in constraint matrix
	int columns=0; //No. of columns in constraint matrix

	/* Variables that store column-major representation of matrix.
	 * These variables will be filled by symphony
	*/
	int *column_start=NULL;// Starting index(in elements array) of each column 
	int *row_indices=NULL;// Row indices corresponding to each non-zero element
	double *elements=NULL;// Non-zero elements of matrix
	
	/* Variables that store row-major representation of matrix.
	 * Filled by a function column_major_to_row_major.
	*/
	double *new_list=NULL; // Non-zero elements of row-major representation
	int *count_per_row=NULL; //Count of non-zero elements in earch row
	int *column_position=NULL; //Column of each non-zero element

	//check whether we have no input and one output argument or not
	CheckInputArgument(pvApiCtx, 0, 0) ; //no input argument
	CheckOutputArgument(pvApiCtx, 1, 1) ; //one output argument

	if(global_sym_env==NULL) //There is no environment opened.
		sciprint("Error: Symphony environment is not initialized.\n");
	else { //There is an environment opened
		int status1=sym_get_num_elements(global_sym_env,&nz_ele); //No. of non-zero elements
		int status2=sym_get_num_cols(global_sym_env , &columns); //Columns
		int status3=sym_get_num_rows(global_sym_env , &rows); //Rows
		int status4=FUNCTION_TERMINATED_ABNORMALLY;
		
		//Make sure functions terminated normally
		if (status1 == status2 && status1 == status3 && status1 == FUNCTION_TERMINATED_NORMALLY){ 
			//Allocate memory for column-major representation			
			column_start=(int*)malloc(sizeof(int) * (columns+1));
			row_indices=(int*)malloc(sizeof(int) * nz_ele);
			elements=(double*)malloc(sizeof(double) * nz_ele);
			
			//Take column-major representation from symphony
			status4=sym_get_matrix(global_sym_env,&nz_ele,column_start,row_indices,elements); 
			if (status1 == status4) { //Check termination status of function, if normal
				
				//Allocate memory for row-major representation 
				new_list=(double*) calloc( nz_ele , sizeof(double));
				count_per_row=(int*) calloc(  rows, sizeof(int ) );
				column_position=(int*) calloc( nz_ele, sizeof(int));
				
				//Convert column-major representation to row-major representation
				column_major_to_row_major(rows,columns,nz_ele,elements,row_indices,column_start,new_list,count_per_row,column_position);
				
				/*
				(Important)Scilab considers indices from 1 , But we have column indices starting from 0 in column_position.
				 Hence add 1 to each index
				*/				
				int iter=0;
				for (;iter < nz_ele ; ++iter) column_position[iter]++;

				}
			else { //If termination status is abnormal
				sciprint("\nFunction invoked unsuccessfully.\n");
				sciprint("\n Is a problem loaded ? \n");
				}				
			}
		else //If termination status of any of functions is abnormal
			sciprint("\nFunction invoked unsuccessfully.\n");
			
		}
	
	//Copy the result to scilab. Location is position next to input arguments.
	SciErr err=createSparseMatrix(pvApiCtx,nbInputArgument(pvApiCtx)+1,rows,columns,nz_ele,count_per_row,column_position,new_list);

	/*
	 *Free allocated memory before exit
	*/
	free(row_indices);
	free(column_start);
	free(elements);
	free(new_list);
	free(count_per_row);
	free(column_position);

	if (err.iErr){ //Process error
        printError(&err, 0);
		AssignOutputVariable(pvApiCtx, 1) = 0;
        return 1;
    	}

	//assign result position to output argument
	AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1;
	//ReturnArguments(pvApiCtx);
	return 0;
	}
}

/*
 * It converts column-major representation to row-major representation
 * :: ARGUMENTS ::
 * rows - No. of rows IN
 * columns - No. of columns IN
 * nz_ele - No. of non-zero elements IN 
 * elements - Non-zero elements in column-major representation IN
 * row_indices - Row index( starts from 0 : symphony) of each non-zero element	IN
 * column_start - Starting index in elements of each column 	IN
 * new_list - Non-zero elements in row-major representation	 OUT 
 * count_per_row - Count of non-zero elements in each row	OUT
 * column_position - Column index ( starts from 0 (we'll add 1 to each index later)) of each non-zero element	OUT
*/
void column_major_to_row_major(int rows,int columns,int nz_ele,double *elements,int *row_indices,int *column_start,double *new_list,int *count_per_row,int *column_position) {

	int iter=0,iter2,iter3=0,index=0;
	for (iter=0;iter < rows;++iter) {
		for (iter2=0;iter2 < nz_ele;++iter2) {
			if (row_indices[iter2] == iter) {
				count_per_row[iter]++; //Count of non-zero elements per row.
				new_list[index]=elements[iter2];
				for (iter3=0; iter3 < columns+1 ; ++iter3) {
					if (iter2 < column_start[iter3])
						break;
					}
				column_position[index] = iter3 - 1;
				index++ ;
				}
			}
		}
	}