Skip to content

Commit eed5f42

Browse files
authored
Merge pull request #64 from rajithv/exception
Exception Handling
2 parents bc52a2d + 7de5e6d commit eed5f42

File tree

8 files changed

+114
-47
lines changed

8 files changed

+114
-47
lines changed

ext/symengine/ruby_basic.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ VALUE cbasic_alloc(VALUE klass)
1818
return Data_Wrap_Struct(klass, NULL, cbasic_free_heap, struct_ptr);
1919
}
2020

21-
VALUE cbasic_binary_op(VALUE self, VALUE operand2,
22-
void (*cwfunc_ptr)(basic_struct *, const basic_struct *,
23-
const basic_struct *))
21+
VALUE cbasic_binary_op(
22+
VALUE self, VALUE operand2,
23+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *,
24+
const basic_struct *))
2425
{
2526
basic_struct *this, *cresult;
26-
VALUE result;
27+
VALUE result = Qnil;
2728

2829
basic cbasic_operand2;
2930
basic_new_stack(cbasic_operand2);
@@ -32,27 +33,37 @@ VALUE cbasic_binary_op(VALUE self, VALUE operand2,
3233
sympify(operand2, cbasic_operand2);
3334

3435
cresult = basic_new_heap();
35-
cwfunc_ptr(cresult, this, cbasic_operand2);
36-
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
37-
cresult);
38-
basic_free_stack(cbasic_operand2);
3936

37+
symengine_exceptions_t error_code
38+
= cwfunc_ptr(cresult, this, cbasic_operand2);
39+
if (error_code == SYMENGINE_NO_EXCEPTION) {
40+
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL,
41+
cbasic_free_heap, cresult);
42+
basic_free_stack(cbasic_operand2);
43+
} else {
44+
basic_free_stack(cbasic_operand2);
45+
raise_exception(error_code);
46+
}
4047
return result;
4148
}
4249

43-
VALUE cbasic_unary_op(VALUE self,
44-
void (*cwfunc_ptr)(basic_struct *, const basic_struct *))
50+
VALUE cbasic_unary_op(VALUE self, symengine_exceptions_t (*cwfunc_ptr)(
51+
basic_struct *, const basic_struct *))
4552
{
4653
basic_struct *this, *cresult;
47-
VALUE result;
54+
VALUE result = Qnil;
4855

4956
Data_Get_Struct(self, basic_struct, this);
5057

5158
cresult = basic_new_heap();
52-
cwfunc_ptr(cresult, this);
53-
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
54-
cresult);
5559

60+
symengine_exceptions_t error_code = cwfunc_ptr(cresult, this);
61+
if (error_code == SYMENGINE_NO_EXCEPTION) {
62+
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL,
63+
cbasic_free_heap, cresult);
64+
} else {
65+
raise_exception(error_code);
66+
}
5667
return result;
5768
}
5869

@@ -93,8 +104,8 @@ VALUE cbasic_diff(VALUE self, VALUE operand2)
93104
sympify(operand2, cbasic_operand2);
94105

95106
cresult = basic_new_heap();
96-
int status = basic_diff(cresult, this, cbasic_operand2);
97-
if (status == 0) {
107+
symengine_exceptions_t status = basic_diff(cresult, this, cbasic_operand2);
108+
if (status == SYMENGINE_RUNTIME_ERROR) {
98109
basic_free_stack(cbasic_operand2);
99110
basic_free_heap(cresult);
100111
return Qnil;

ext/symengine/ruby_basic.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ void cbasic_free_heap(void *ptr);
1212

1313
VALUE cbasic_alloc(VALUE klass);
1414

15-
VALUE cbasic_binary_op(VALUE self, VALUE operand2,
16-
void (*cwfunc_ptr)(basic_struct *, const basic_struct *,
17-
const basic_struct *));
15+
VALUE cbasic_binary_op(
16+
VALUE self, VALUE operand2,
17+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *,
18+
const basic_struct *));
1819

19-
VALUE cbasic_unary_op(VALUE self,
20-
void (*cwfunc_ptr)(basic_struct *, const basic_struct *));
20+
VALUE cbasic_unary_op(VALUE self, symengine_exceptions_t (*cwfunc_ptr)(
21+
basic_struct *, const basic_struct *));
2122

2223
VALUE cbasic_add(VALUE self, VALUE operand2);
2324

ext/symengine/ruby_utils.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,20 @@ VALUE cutils_sympify(VALUE self, VALUE operand)
1717

1818
VALUE cutils_evalf(VALUE self, VALUE operand, VALUE prec, VALUE real)
1919
{
20-
VALUE result;
20+
VALUE result = Qnil;
2121

2222
basic_struct *cresult;
2323
cresult = basic_new_heap();
2424

2525
sympify(operand, cresult);
26-
basic_evalf(cresult, cresult, NUM2INT(prec), (real == Qtrue ? 1 : 0));
27-
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
28-
cresult);
29-
26+
symengine_exceptions_t error_code
27+
= basic_evalf(cresult, cresult, NUM2INT(prec), (real == Qtrue ? 1 : 0));
28+
29+
if (error_code == SYMENGINE_NO_EXCEPTION) {
30+
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL,
31+
cbasic_free_heap, cresult);
32+
} else {
33+
raise_exception(error_code);
34+
}
3035
return result;
3136
}

ext/symengine/symengine_utils.c

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,31 +199,37 @@ VALUE Klass_of_Basic(const basic_struct *basic_ptr)
199199
}
200200
}
201201

202-
VALUE function_onearg(void (*cwfunc_ptr)(basic_struct *, const basic_struct *),
203-
VALUE operand1)
202+
VALUE function_onearg(
203+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *),
204+
VALUE operand1)
204205
{
205206
basic_struct *cresult;
206-
VALUE result;
207+
VALUE result = Qnil;
207208

208209
basic cbasic_operand1;
209210
basic_new_stack(cbasic_operand1);
210211
sympify(operand1, cbasic_operand1);
211212

212213
cresult = basic_new_heap();
213-
cwfunc_ptr(cresult, cbasic_operand1);
214-
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
215-
cresult);
216-
basic_free_stack(cbasic_operand1);
217-
214+
symengine_exceptions_t error_code = cwfunc_ptr(cresult, cbasic_operand1);
215+
if (error_code == SYMENGINE_NO_EXCEPTION) {
216+
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL,
217+
cbasic_free_heap, cresult);
218+
basic_free_stack(cbasic_operand1);
219+
} else {
220+
basic_free_stack(cbasic_operand1);
221+
raise_exception(error_code);
222+
}
218223
return result;
219224
}
220225

221-
VALUE function_twoarg(void (*cwfunc_ptr)(basic_struct *, const basic_struct *,
226+
VALUE function_twoarg(
227+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *,
222228
const basic_struct *),
223-
VALUE operand1, VALUE operand2)
229+
VALUE operand1, VALUE operand2)
224230
{
225231
basic_struct *cresult;
226-
VALUE result;
232+
VALUE result = Qnil;
227233

228234
basic cbasic_operand1;
229235
basic_new_stack(cbasic_operand1);
@@ -234,11 +240,43 @@ VALUE function_twoarg(void (*cwfunc_ptr)(basic_struct *, const basic_struct *,
234240
sympify(operand2, cbasic_operand2);
235241

236242
cresult = basic_new_heap();
237-
cwfunc_ptr(cresult, cbasic_operand1, cbasic_operand2);
238-
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL, cbasic_free_heap,
239-
cresult);
240-
basic_free_stack(cbasic_operand1);
241-
basic_free_stack(cbasic_operand2);
243+
symengine_exceptions_t error_code
244+
= cwfunc_ptr(cresult, cbasic_operand1, cbasic_operand2);
242245

246+
if (error_code == SYMENGINE_NO_EXCEPTION) {
247+
result = Data_Wrap_Struct(Klass_of_Basic(cresult), NULL,
248+
cbasic_free_heap, cresult);
249+
basic_free_stack(cbasic_operand1);
250+
basic_free_stack(cbasic_operand2);
251+
} else {
252+
basic_free_stack(cbasic_operand1);
253+
basic_free_stack(cbasic_operand2);
254+
raise_exception(error_code);
255+
}
243256
return result;
244257
}
258+
259+
void raise_exception(symengine_exceptions_t error_code)
260+
{
261+
char *str = "";
262+
switch (error_code) {
263+
case SYMENGINE_NO_EXCEPTION:
264+
return;
265+
case SYMENGINE_RUNTIME_ERROR:
266+
str = "Runtime Error";
267+
break;
268+
case SYMENGINE_DIV_BY_ZERO:
269+
str = "Division by Zero";
270+
break;
271+
case SYMENGINE_NOT_IMPLEMENTED:
272+
str = "Not Implemented";
273+
break;
274+
case SYMENGINE_UNDEFINED:
275+
str = "Undefined";
276+
break;
277+
case SYMENGINE_PARSE_ERROR:
278+
str = "Parse Error";
279+
break;
280+
}
281+
rb_raise(rb_eRuntimeError, "%s", str);
282+
}

ext/symengine/symengine_utils.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ void get_symintfromval(VALUE operand2, basic_struct *cbasic_operand2);
1717
VALUE Klass_of_Basic(const basic_struct *basic_ptr);
1818
// Returns the result from the function pointed by cwfunc_ptr: for one argument
1919
// functions
20-
VALUE function_onearg(void (*cwfunc_ptr)(basic_struct *, const basic_struct *),
21-
VALUE operand1);
20+
VALUE function_onearg(
21+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *),
22+
VALUE operand1);
2223
// Returns the result from the function pointed by cwfunc_ptr: for two argument
2324
// functions
24-
VALUE function_twoarg(void (*cwfunc_ptr)(basic_struct *, const basic_struct *,
25+
VALUE function_twoarg(
26+
symengine_exceptions_t (*cwfunc_ptr)(basic_struct *, const basic_struct *,
2527
const basic_struct *),
26-
VALUE operand1, VALUE operand2);
28+
VALUE operand1, VALUE operand2);
29+
void raise_exception(symengine_exceptions_t error_code);
2730

2831
#endif // SYMENGINE_UTILS_H_

spec/functions_spec.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@
6666
expect(SymEngine::cos(pi)).to eq(-1)
6767
expect(SymEngine::tan(pi)).to eq(0)
6868
expect(SymEngine::csc(pi/2)).to eq(1)
69+
expect { SymEngine::csc(pi) }.to raise_error(RuntimeError)
6970
expect(SymEngine::sec(pi)).to eq(-1)
71+
expect { SymEngine::sec(pi/2) }.to raise_error(RuntimeError)
7072
expect(SymEngine::cot(pi/4)).to eq(1)
73+
expect { SymEngine::cot(pi) }.to raise_error(RuntimeError)
7174

7275
expect(SymEngine::asin(1)).to eq(pi/2)
7376
expect(SymEngine::acos(1)).to eq(0)

spec/integer_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,10 @@
6767
end
6868
end
6969
end
70+
71+
describe 'errors' do
72+
it 'raises an exception on division by zero' do
73+
expect { SymEngine(1)/SymEngine(0) }.to raise_error(RuntimeError)
74+
end
75+
end
7076
end

symengine_version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ab5f5da3a9aa501a7a5bf7889a68f67c21a3b9c8
1+
d674459efdfb2871643a2ae4616715ba98323ada

0 commit comments

Comments
 (0)