File: crm_svm_matrix.h

package info (click to toggle)
crm114 20100106-10
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 3,184 kB
  • sloc: ansic: 34,910; sh: 617; makefile: 578; lisp: 208
file content (881 lines) | stat: -rw-r--r-- 23,499 bytes parent folder | download | duplicates (4)
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
//	crm_svm_matrix.h - Support Vector Machine

////////////////////////////////////////////////////////////////////////
//    This code is originally copyright and owned by William
//    S. Yerazunis as file crm_neural_net.  In return for addition of 
//    significant derivative work, Jennifer Barry is hereby granted a full 
//    unlimited license to use this code, includng license to relicense under 
//    other licenses.
////////////////////////////////////////////////////////////////////////
//
// Copyright 2009 William S. Yerazunis.
// This file is under GPLv3, as described in COPYING.

#ifndef __CRM_SVM_MATRIX__H
#define __CRM_SVM_MATRIX__H

#include "crm_svm_matrix_util.h"

/*******************************************************************
 *A matrix/vector library that deals with different data structures
 *for representing vectors transparently.
 *
 *The functions in matrix.c are commented.  See them for
 *details on this library.
 ******************************************************************/

#define MATR_DEFAULT_VECTOR_SIZE 1200 //sparse arrays start at this size
                                      //unless otherwise specified
#define MATR_COMPACT 1
#define MATR_PRECISE 0
#define QSORT_COUNTING_CUTOFF 7e7 //with this many non-zero elts or above 
                                  //we use counting sort, not q-sort

extern int MATR_DEBUG_MODE;        //debug setting.  see crm_svm_matrix_util.h
                                  //for possible modes

//Possible vector types.
typedef enum {
  NON_SPARSE,
  SPARSE_ARRAY,
  SPARSE_LIST
} VectorType;

typedef enum {
  COUNTING,
  MERGE,
  QSORT
} SortingAlgorithms;


typedef union {
  PreciseSparseNode *pcurr;
  CompactSparseNode *ccurr;
  long nscurr;
} VectorIterator;


//data for non-sparse
//can be either doubles or ints
typedef union {
  int *compact;
  double *precise;
} NSData;

//vectors can be either expanding arrays, lists,
//or arrays of NSData
typedef union {
  ExpandingArray *sparray;   //SPARSSE_ARRAY vector
  SparseElementList *splist; //SPARSE_LIST vector
  NSData nsarray;            //NON_SPARSE vector
} VectorData;

//vector struct
typedef struct {
  VectorData data;  //data stored in the vector
  unsigned int dim; //# columns (dimension) in the vector
  int nz,           //# non-zero elements (nz = dim if v is NON_SPARSE) 
    compact,        //flag for compactness
    size,           //starting size for expanding arrays
    was_mapped;     //1 if the vector was mapped into memory
  VectorType type;  //flag for type
} Vector;

//matrix struct
typedef struct {
  Vector **data;     //list of pointers to rows
  unsigned int rows, //# rows in the matrix
    cols;            //# columns in the matrix
  int nz,            //# non-zero elements (nz = rows*cols if M is NON_SPARSE)
    compact,         //flag for compactness
    size,            //starting size for expanding arrays
    was_mapped;      //1 if the matrix was mapped into memory
  VectorType type;   //flag for type
} Matrix;

//Matrix functions
Matrix *matr_make(unsigned int rows, unsigned int cols, VectorType type, 
		  int compact);
Matrix *matr_make_size(unsigned int rows, unsigned int cols, VectorType type, 
		       int compact, int init_size);
void matr_set_row(Matrix *A, unsigned int r, Vector *v);
void matr_shallow_row_copy(Matrix *M, unsigned int r, Vector *v);
void matr_set_col(Matrix *A, unsigned int c, Vector *v);
void matr_add_row(Matrix *M);
void matr_add_nrows(Matrix *M, unsigned int n);
void matr_add_col(Matrix *M);
void matr_add_ncols(Matrix *M, unsigned int n);
void matr_remove_row(Matrix *M, unsigned int r);
void matr_erase_row(Matrix *M, unsigned int r);
void matr_remove_col(Matrix *M, unsigned int c);
ExpandingArray *matr_remove_zero_rows(Matrix *M);
ExpandingArray *matr_remove_zero_cols(Matrix *M);
void matr_append_matr(Matrix **to_ptr, Matrix *from);
void matr_vector(Matrix *M, Vector *v, Vector *ret);
void matr_vector_seq(Matrix **A, int nmatrices, unsigned int maxrows,
		     Vector *w, Vector *z);
void matr_transpose(Matrix *A, Matrix *T);
void matr_multiply(Matrix *M1, Matrix *M2, Matrix *ret);
int matr_iszero(Matrix *M);
void matr_convert_nonsparse_to_sparray(Matrix *M, ExpandingArray *colMap);
void matr_print(Matrix *M);
void matr_write(Matrix *M, char *filename);
void matr_write_fp(Matrix *M, FILE *out);
size_t matr_write_bin(Matrix *M, char *filename);
size_t matr_write_bin_fp(Matrix *M, FILE *fp);
Matrix *matr_read_bin(char *filename);
Matrix *matr_read_bin_fp(FILE *fp);
Matrix *matr_map(void **addr, void *last_addr);
void matr_free(Matrix *M);

//inlined matrix functions defined in this file
//(inlining is compiler discretion)
static inline void matr_set(Matrix *M, unsigned int r, unsigned int c, 
			    double d);
static inline double matr_get(Matrix *M, unsigned int r, unsigned int c);
static inline Vector *matr_get_row(Matrix *M, unsigned int r);


//Vector functions
Vector *vector_make(unsigned int dim, VectorType type, int compact);
Vector *vector_make_size(unsigned int dim, VectorType type, int compact, 
			 int init_size);
void vector_copy(Vector *from, Vector *to);
void vector_set(Vector *v, unsigned int i, double d);
double vector_get(Vector *v, unsigned int i);
void vector_add_col(Vector *v);
void vector_add_ncols(Vector *v, unsigned int n);
void vector_remove_col(Vector *v, unsigned int c);
int vector_iszero(Vector *V);
int vector_equals(Vector *v1, Vector *v2);
void vector_zero(Vector *v);
void vector_add(Vector *v1, Vector *v2, Vector *ret);
void vector_multiply(Vector *v, double s, Vector *ret);
double dot(Vector *v1, Vector *v2);
void vector_add_multiple(Vector *base, Vector *toadd, 
			 double factor, Vector *ret);
double vector_dist2(Vector *v1, Vector *v2);
void vector_convert_nonsparse_to_sparray(Vector *v, ExpandingArray *colMap);
void vector_print(Vector *v);
void vector_write(Vector *v, char *filename);
void vector_write_fp(Vector *v, FILE *out);
void vector_write_sp(Vector *v, char *filename);
void vector_write_sp_fp(Vector *v, FILE *out);
size_t vector_write_bin(Vector *v, char *filename);
size_t vector_write_bin_fp(Vector *v, FILE *fp);
Vector *vector_read_bin(char *filename);
Vector *vector_read_bin_fp(FILE *fp);
Vector *vector_map(void **addr, void *last_addr);
void *vector_memmove(void *to, Vector *from);
size_t vector_size(Vector *v);
void vector_free(Vector *v);

//inline'd functions defined in this file
//(inlining is compiler discretion)
static inline unsigned int vector_dim(Vector *v);
static inline int vector_num_elts(Vector *v);
static inline double norm2(Vector *v);
static inline double norm(Vector *v);
static inline double vector_dist(Vector *v1, Vector *v2) ;

//Vector iterator functions
void vectorit_zero_elt(VectorIterator *vit, Vector *v);
void vectorit_insert(VectorIterator *vit, unsigned int c, double d, Vector *v);
void vectorit_find(VectorIterator *vit, unsigned int c, Vector *v);
void vectorit_set_col(VectorIterator vit, unsigned int c, Vector *v);

//defined in this file - forced to be inline'd at high optimization
MY_INLINE void vectorit_set_at_beg(VectorIterator *vit, Vector *v);
MY_INLINE void vectorit_set_at_end(VectorIterator *vit, Vector *v);
MY_INLINE double vectorit_curr_val(VectorIterator vit, Vector *v);
MY_INLINE unsigned int vectorit_curr_col(VectorIterator vit, Vector *v);
MY_INLINE void vectorit_prev(VectorIterator *vit, Vector *v);
MY_INLINE void vectorit_next(VectorIterator *vit, Vector *v);
MY_INLINE int vectorit_past_end(VectorIterator vit, Vector *v);
MY_INLINE int vectorit_past_beg(VectorIterator vit, Vector *v);
MY_INLINE void vectorit_copy(VectorIterator from, VectorIterator *to);


/*************INLINE FUNCTION DEFINITIONS***********************************/


//Matrix
/*************************************************************************
 *Gets a pointer to a row of a matrix.
 *
 *INPUT: A: matrix from which to get a row.
 * r: row to get.
 *
 *OUTPUT: A pointer to row r of matrix M.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/

static inline Vector *matr_get_row(Matrix *A, unsigned int r) {
  //yay, easy :)
  if (A && A->data && r >= 0 && r < A->rows) {
    return A->data[r];
  }
  if (MATR_DEBUG_MODE) {
    fprintf(stderr, "matr_get_row: bad arguments.\n");
  }
  return NULL;
} 

/*************************************************************************
 *Sets an entry of a matrix.
 *
 *INPUT: M: matrix in which to set an entry.
 * r: row of the entry.
 * c: column of the entry.
 * d: value to set the entry to.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: d is non-zero = ammortized O(lg(S/R)), d = 0 = O(S/R)
 * SPARSE_LIST: O(S/R)
 *************************************************************************/

static inline void matr_set(Matrix *M, unsigned int r, unsigned int c, 
			    double d) {
  int nz;
  if (!M || !M->data || r < 0 || r >= M->rows || !M->data[r]) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "matr_set: bad arguments.\n");
    }
    return;
  }
  nz = M->data[r]->nz;
  vector_set(M->data[r], c, d);
  M->nz += M->data[r]->nz - nz;
}

/*************************************************************************
 *Gets an entry of a matrix.
 *
 *INPUT: M: matrix from which to get an entry.
 * r: row of the entry.
 * c: column of the entry.
 *
 *OUTPUT: the value at r,c of matrix M
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(lg(S/R))
 * SPARSE_LIST: O(S/R)
 *************************************************************************/

static inline double matr_get(Matrix *M, unsigned int r, unsigned int c) {
  if (!M || !M->data || r < 0 || r >= M->rows || !M->data[r]) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "matr_set: bad arguments.\n");
    }
    return 0;
  }
  return vector_get(M->data[r], c);
}

//Vector




/*************************************************************************
 *Dimension of a vector.
 *
 *INPUT: v: vector
 *
 *OUTPUT: The dimension (ie number of rows/columns) of v
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/

static inline unsigned int vector_dim(Vector *v) {
  if (!v) {
    return 0;
  }
  return v->dim;
}

/*************************************************************************
 *Number of elements of a vector.
 *
 *INPUT: v: vector
 *
 *OUTPUT: The dimension (ie number of rows/columns) of v if v is NON_SPARSE
 * or the number of non-zero elements of v if v is SPARSE
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/

static inline int vector_num_elts(Vector *v) {
  if (!v) {
    return 0;
  }
  return v->nz;
}


/*************************************************************************
 *Squared norm.  Note that finding square roots can be time consuming so
 *use this function to avoid that when possible.
 *
 *INPUT: v: vector to find the norm of
 *
 *OUTPUT: ||v||^2
 *
 *TIME:
 * NON_SPARSE: O(c)
 * SPARSE_ARRAY: O(s)
 * SPARSE_LIST: O(s)
 *************************************************************************/

static inline double norm2(Vector *v) {
  return dot(v, v);
}

/*************************************************************************
 *Norm of a vector.
 *
 *INPUT: v: vector to find the norm of
 *
 *OUTPUT: ||v||
 *
 *TIME:
 * NON_SPARSE: O(c)
 * SPARSE_ARRAY: O(s)
 * SPARSE_LIST: O(s)
 *************************************************************************/

static inline double norm(Vector *v) {
  return (sqrt(dot(v,v)));
}


/*************************************************************************
 *Distance between two vectors.
 *
 *INPUT: v1: first vector
 * v2: second vector
 *
 *OUTPUT: ||v1 - v2||
 *
 *TIME:
 * Both NON_SPARSE: O(c)
 * One NON_SPARSE, one SPARSE: O(s) + O(c)
 * Both SPARSE: O(s_1) + O(s_2)
 *************************************************************************/

static inline double vector_dist(Vector *v1, Vector *v2) {
  double d = vector_dist2(v1, v2);
  
  if (d > 0) {
    return sqrt(d);
  }

  return -1;
}


//Vector Iterator functions

/*************************************************************************
 *Set the iterator to the beginning of a vector.
 *
 *INPUT: v: vector to traverse from the beginning
 *
 *OUTPUT: vit is set to the beginning of vector v
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE void vectorit_set_at_beg(VectorIterator *vit, Vector *v) {

  if (!v || !vit) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_set_at_beg: null arguments.\n");
    }
    if (vit) {
      vit->nscurr = -1;
    }
    return;
  }

  switch (v->type) {
  case NON_SPARSE:
    {
      vit->nscurr = 0;
      return;
    }
  case SPARSE_ARRAY:
    {
      //nscurr needs to be the actual index
      //in order that zero-ing an element in vector_add etc
      //doesn't mess things up
      if (!v->data.sparray) {
	vit->nscurr = 0;
      } else {
	vit->nscurr = v->data.sparray->first_elt;
      }
      return;
    }
  case SPARSE_LIST:
    {
      if (v->compact) {
	if (v->data.splist) {
	  vit->ccurr = (v->data.splist->head.compact);
	} else {
	  vit->ccurr = NULL;
	}
      } else {
	if (v->data.splist) {
	  vit->pcurr = (v->data.splist->head.precise);
	} else {
	  vit->pcurr = NULL;
	}
      }
      return;
    }
  default:
    {
      vit->nscurr = -1;
      return;
    }
  }
}


/*************************************************************************
 *Set the iterator to the end of a vector.
 *
 *INPUT: v: vector to traverse from the end
 *
 *OUTPUT: vit is set to the end of vector v
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE void vectorit_set_at_end(VectorIterator *vit, Vector *v) {

  if (!v || !vit) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_set_at_end: null arguments.\n");
    }
    if (vit) {
      vit->nscurr = -1;
    }
    return;
  }

  switch (v->type) {
  case NON_SPARSE:
    {
      vit->nscurr = v->dim-1;
      break;
    }
  case SPARSE_ARRAY:
    {
      if (!v->data.sparray) {
	vit->nscurr = 0;
      } else {
	vit->nscurr = v->data.sparray->last_elt;
      }
      break;
    }
  case SPARSE_LIST:
    { 
      if (v->compact) {
	if (!v->data.splist) {
	  vit->ccurr = NULL;
	} else {
	  vit->ccurr = v->data.splist->tail.compact;
	}
      } else {
	if (!v->data.splist) {
	  vit->pcurr = NULL;
	} else {
	  vit->pcurr = v->data.splist->tail.precise;
	}
      }
      break;
    }
  default:
    {
      vit->nscurr = -1;
      if (MATR_DEBUG_MODE) {
	fprintf(stderr, "vectorit_set_at_end: unrecognized type.\n");
      }
      return;
    }
  }
}

/*************************************************************************
 *Get the value (data) of the element that the iterator is pointing to.
 *
 *INPUT: vit: the vector iterator, pointing to some element in v
 * v: the vector vit is traversing
 *
 *OUTPUT: The data associated with the element vit is pointing to or
 * -RAND_MAX if vit is not traversing v.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE double vectorit_curr_val(VectorIterator vit, Vector *v) {

  if (!v) {
    //if (MATR_DEBUG_MODE) {
    //fprintf(stderr, "vectorit_curr_col: null vector.\n");
    //}
    return -RAND_MAX;
  }

  switch (v->type) {
  case SPARSE_ARRAY:  
    if (v->data.sparray &&
	vit.nscurr >= v->data.sparray->first_elt &&
	vit.nscurr <= v->data.sparray->last_elt) {
      if (v->compact && v->data.sparray->data.compact) {
	return (double)v->data.sparray->data.compact[vit.nscurr].s.data;
      }
      if (!(v->compact) && (v->data.sparray->data.precise)) {
	return v->data.sparray->data.precise[vit.nscurr].s.data;
      }
    }
    return -RAND_MAX;
  case SPARSE_LIST:
    {
      if (v->compact && vit.ccurr) {
	return (double)vit.ccurr->data.data;
      }
      if (!(v->compact) && vit.pcurr) {
	return vit.pcurr->data.data;
      }
      return -RAND_MAX;
    }
  case NON_SPARSE:
    {
      if (vit.nscurr >= 0 && vit.nscurr < v->dim) {
	if (v->compact && v->data.nsarray.compact) {
	  return (double)v->data.nsarray.compact[vit.nscurr];
	}
	if (!(v->compact) && v->data.nsarray.precise) {
	  return v->data.nsarray.precise[vit.nscurr];
	}
      }
      return -RAND_MAX;
    }
  default:
    {
      return -RAND_MAX;
    }
  }

  return -RAND_MAX;

}

/*************************************************************************
 *Get the column of the element that the iterator is pointing to.
 *
 *INPUT: vit: the vector iterator, pointing to some element in v
 * v: the vector vit is traversing
 *
 *OUTPUT: The column associated with the element vit is pointing to or v->dim
 * if vit is past the beginning or end of v.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *
 *WARNINGS:
 *1) This returns v->dim even if vit is past the BEGINNING of v.  This is
 *   because column numbers need to be unsigned.  Therefore, you need
 *   to explicitly check if an iterator is past the beginning of a vector 
 *   - you can't count on this returning a negative value if the iterator
 *   is past the beginning.
 *************************************************************************/  

MY_INLINE unsigned int vectorit_curr_col(VectorIterator vit, Vector *v) {

  if (!v) {
    if (MATR_DEBUG_MODE) {
    fprintf(stderr, "vectorit_curr_col: null vector.\n");
    }
    return MAX_INT_VAL;
  }

  switch (v->type) {
  case SPARSE_ARRAY:
    if (v->data.sparray && v->data.sparray->data.compact &&
	vit.nscurr >= v->data.sparray->first_elt &&
	vit.nscurr <= v->data.sparray->last_elt) {
      if (v->compact && v->data.sparray->data.compact) {
	return v->data.sparray->data.compact[vit.nscurr].s.col;
      }
      if (!(v->compact) && (v->data.sparray->data.precise)) {
	return v->data.sparray->data.precise[vit.nscurr].s.col;
      }
    }
    return v->dim;
  case SPARSE_LIST:
    {
      if (v->compact && vit.ccurr) {
	return vit.ccurr->data.col;
      }
      if (!(v->compact) && vit.pcurr) {
	return vit.pcurr->data.col;
      }
      return v->dim;
    }
  case NON_SPARSE:
    {
      return vit.nscurr;
    }
  default:
    {
      return v->dim;
    }
  }

  return v->dim;

}


/*************************************************************************
 *Move to the previous element in the vector.  Sets past_beg and unsets
 *past_end if appropriate.
 *
 *INPUT: v: the vector vit is traversing
 *
 *OUTPUT: vit points to the previous element in the vector or is past_beg.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE void vectorit_prev(VectorIterator *vit, Vector *v) {
  
  if (!v || !vit) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_prev: null arguments.\n");
    }
    if (vit) {
      vit->nscurr = -1;
    }
    return;
  }

  switch (v->type) {
  case NON_SPARSE:
  case SPARSE_ARRAY:
    vit->nscurr--;
    return;
  case SPARSE_LIST:
    if ((v->compact)) {
      if (vit->ccurr) {
	vit->ccurr = vit->ccurr->prev;
      } else {
	vit->ccurr = v->data.splist->tail.compact;
      }
    } else {
      if (vit->pcurr) {
	vit->pcurr = vit->pcurr->prev;
      } else {
	vit->pcurr = v->data.splist->tail.precise;
      }
      
    }
  default:
    return;
  }
}

/*************************************************************************
 *Move to the next element in the vector.
 *
 *INPUT: v: the vector vit is traversing
 *
 *OUTPUT: vit points to the next element in the vector or is past_end.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE void vectorit_next(VectorIterator *vit, Vector *v) {
  if (!v || !vit) {
    //if (MATR_DEBUG_MODE) {
    //fprintf(stderr, "vectorit_next: null arguments.\n");
    //}
    return;
  }
  
  switch (v->type) {
  case NON_SPARSE:
  case SPARSE_ARRAY:
    vit->nscurr++;
    return;
  case SPARSE_LIST:
    if ((v->compact)) {
      if (vit->ccurr) {
	vit->ccurr = vit->ccurr->next;
      } else {
	vit->ccurr = v->data.splist->head.compact;
      }
    } else {
      if (vit->pcurr) {
	vit->pcurr = vit->pcurr->next;
      } else {
	vit->pcurr = v->data.splist->head.precise;
      }
      
    }
  default:
    return;
  }
}


/*************************************************************************
 *Checks if an iterator is past the end of the vector.
 *
 *INPUT: vit: the iterator
 * v: the vector vit is traversing
 *
 *OUTPUT: 1 if vit is past the end of v, 0 else
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE int vectorit_past_end(VectorIterator vit, Vector *v) {
  if (!v) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_past_end: null arguments.\n");
    }
    return 1;
  }

  switch (v->type) {
  case SPARSE_ARRAY:
    if (!v->data.sparray || vit.nscurr > v->data.sparray->last_elt ||
	v->data.sparray->first_elt > v->data.sparray->last_elt) {
      return 1;
    }
    return 0;
  case SPARSE_LIST:
    if (v->compact && !vit.ccurr) {
      return 1;
    }
    if (!(v->compact) && !vit.pcurr) {
      return 1;
    }
    return 0;
  case NON_SPARSE:
    if (vit.nscurr >= v->dim) {
      return 1;
    }
    return 0;
  default:
    return 1;
  }
}

/*************************************************************************
 *Checks if an iterator is past the beginning of the vector.
 *
 *INPUT: vit: the iterator
 * v: the vector vit is traversing
 *
 *OUTPUT: 1 if vit is past the beginning of v, 0 else
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE int vectorit_past_beg(VectorIterator vit, Vector *v) {
  if (!v) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_past_end: null arguments.\n");
    }
    return 1;
  }

  switch (v->type) {
  case SPARSE_ARRAY:
    if (!(v->data.sparray) || vit.nscurr < v->data.sparray->first_elt
	|| v->data.sparray->first_elt > v->data.sparray->last_elt) {
      return 1;
    }
    return 0;
  case SPARSE_LIST:
    if (v->compact && !vit.ccurr) {
      return 1;
    }
    if (!(v->compact) && !vit.pcurr) {
      return 1;
    }
    return 0;
  case NON_SPARSE:
    if (vit.nscurr < 0) {
      return 1;
    }
    return 0;
  default:
    return 1;
  }
}

/*************************************************************************
 *Copy one vector iterator to another.
 *
 *INPUT: from: vector iterator to copy from
 *
 *OUTPUT: to = from.
 *
 *TIME:
 * NON_SPARSE: O(1)
 * SPARSE_ARRAY: O(1)
 * SPARSE_LIST: O(1)
 *************************************************************************/  

MY_INLINE void vectorit_copy(VectorIterator from, VectorIterator *to) {
  if (!to) {
    if (MATR_DEBUG_MODE) {
      fprintf(stderr, "vectorit_copy: null to vector.\n");
    }
    return;
  }
  to->nscurr = from.nscurr;
}

#endif //crm_svm_matrix.h