_substract_inplace() moved to XS code
[language-befunge-vector-xs.git] / XS.xs
blob6ec101c3dc59164686cb7cd276801fe5a2998ea4
1 /*
3 # This file is part of Language::Befunge::Vector::XS.
4 # Copyright (c) 2008 Jerome Quelin, all rights reserved.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the same terms as Perl itself.
13 #include "EXTERN.h"
14 #include "perl.h"
15 #include "XSUB.h"
17 #include "ppport.h"
20 /* used for constructor new() */
21 typedef int intArray;
22 void* intArrayPtr(int num) {
23     SV* mortal;
24     mortal = sv_2mortal( NEWSV(0, num * sizeof(intArray)) );
25     return SvPVX(mortal);
30 MODULE = Language::Befunge::Vector::XS          PACKAGE = Language::Befunge::Vector::XS
33 #-- CONSTRUCTORS
36 # my $vec = LB::Vector->new( $x [, $y, ...] );
38 # Create a new vector. The arguments are the actual vector data; one
39 # integer per dimension.
41 SV *
42 new( class, array, ... )
43         char*       class;
44         intArray*   array
46         INIT:
47             AV*  self;
48             I32  i;
49             SV*  val;
50             HV*  stash;
52         CODE:
53             /* create the object and populate it */
54             self = newAV();
55             for ( i=0; i<ix_array; i++ ) {
56                 val = newSViv( array[i] );
57                 av_push(self, val);
58             }
60             /* Return a blessed reference to the AV */
61             RETVAL = newRV_noinc( (SV *)self );
62             stash  = gv_stashpv( class, TRUE );
63             sv_bless( (SV *)RETVAL, stash );
65         OUTPUT:
66             RETVAL
70 # my $vec = Language::Befunge::Vector::XS->new_zeroes( $dims );
72 # Create a new vector, set to the origin. The only argument is the dimension of
73 # the vector to be created.
75 # ->new_zeroes(2) is exactly equivalent to ->new([0,0])
77 SV *
78 new_zeroes( class, dimension )
79         char* class;
80         I32   dimension;
82         INIT:
83             AV*  self;
84             I32  i;
85             SV*  zero;
86             HV*  stash;
88         CODE:
89             /* create the object and populate it */
90             self = newAV();
91             for ( i=0; i<dimension; i++ ) {
92                 zero = newSViv(0);
93                 av_push(self, zero);
94             }
96             /* return a blessed reference to the AV */
97             RETVAL = newRV_noinc( (SV *)self );
98             stash  = gv_stashpv( class, TRUE );
99             sv_bless( (SV *)RETVAL, stash );
101         OUTPUT:
102             RETVAL
105 #-- PUBLIC METHODS
107 #- accessors
110 # my $dims = $vec->get_dims;
112 # Return the number of dimensions, an integer.
115 get_dims( self )
116         AV* self;
118     CODE:
119         RETVAL = av_len(self) + 1;
121     OUTPUT:
122         RETVAL
125 # my $val = $vec->get_component( $index );
127 # Return the value for dimension $index.
130 get_component( self, index )
131         AV* self;
132         I32 index;
134     CODE:
135         if ( index < 0 || index > av_len(self) )
136             croak( "No such dimension!" );
137         RETVAL = SvIV( *av_fetch(self, index, 0) );
139     OUTPUT:
140         RETVAL
143 #- mutators
145 # -- PRIVATE METHODS
147 #- inplace math ops
150 # $v1->_substract_inplace($v2);
151 # $v1 -= $v2;
153 # Substract $v2 to $v1, and stores the result back into $v1.
155 AV* _substract_inplace( v1, v2 )
156         AV* v1;
157         AV* v2;
159     INIT:
160         I32 dimv1, dimv2;
161         I32 i;
162         I32 val1, val2;
164     CODE:
165         dimv1 = av_len(v1);
166         dimv2 = av_len(v2);
168         /* sanity checks */
169         if ( dimv1 != dimv2 )
170             croak("uneven dimensions in vector substraction!");
172         for ( i=0 ; i<=dimv1; i++ ) {
173             val1 = SvIV( *av_fetch(v1, i, 0) );
174             val2 = SvIV( *av_fetch(v2, i, 0) );
175             av_store( v1, i, newSViv(val1-val2) );
176             }
177         RETVAL = v1;
179     OUTPUT:
180         RETVAL
183 #- comparison
186 # my $bool = $v1->_compare($v2);
187 # my $bool = $v1 <=> $v2;
189 # Check whether the vectors both point at the same spot. Return 0 if they
190 # do, 1 if they don't.
193 _compare( v1, v2, variant )
194         AV* v1;
195         AV* v2;
196         SV* variant;
198     INIT:
199         I32 dimv1, dimv2;
200         I32 i;
201         I32 val1, val2;
203     CODE:
204         dimv1 = av_len(v1);
205         dimv2 = av_len(v2);
207         /* sanity checks */
208         if ( dimv1 != dimv2 )
209             croak("uneven dimensions in bounds check!");
211         RETVAL = 0;
212         for ( i=0 ; i<=dimv1; i++ ) {
213             val1 = SvIV( *av_fetch(v1, i, 0) );
214             val2 = SvIV( *av_fetch(v2, i, 0) );
215             if ( val1 != val2 ) {
216                 RETVAL = 1;
217                 break;
218             }
219         }
221     OUTPUT:
222         RETVAL