NUMBER number_add(NUMBER num1, NUMBER num2) { int carry, add, i; NUMBER res = number_new(); if (num1.negative) { num1.negative = 0; return number_subtract(num2, num1); } if (num2.negative) { num2.negative = 0; return number_subtract(num1, num2); } for (i = add = carry = 0; i < num1.numbers || i < num2.numbers || carry; i++, add = 0) { if (num1.numbers > i) add += num1.number[i]; if (num2.numbers > i) add += num2.number[i]; add += carry; carry = 0; number_insert_high(&res, add % 10); carry = add / 10; } return res; }
tm_obj tm_div( tm_obj a, tm_obj b){ if( a.type == b.type && a.type == TM_NUM){ return number_new( get_num(a) / get_num(b) ); } tm_raise("tm_div: can not div @ and @", a,b ); return obj_none; }
tm_obj tm_mod( tm_obj a, tm_obj b){ if( a.type == b.type && a.type == TM_NUM){ return number_new((long)get_num(a) % (long)get_num(b) ); } tm_raise("tm_mod: can not mod @ and @", a,b ); return obj_none; }
static pobject mod(pobject env, pobject params) { pobject o1 = eval(env, cons_nth(params, 1)); pobject o2 = eval(env, cons_nth(params, 2)); return (is_number(o1) && is_number(o2)) ? gc_add((number_new( (int)number_value(o1) % (int)number_value(o2) ))) : NIL; }
void builtin_math_init(pobject *env) { cons_assoc_set(env, symbol_intern("*pi*"), gc_add(number_new(M_PI)), 1); cons_assoc_set(env, symbol_intern("+"), gc_add(cfunc_new(plus)), 1); cons_assoc_set(env, symbol_intern("-"), gc_add(cfunc_new(minus)), 1); cons_assoc_set(env, symbol_intern("*"), gc_add(cfunc_new(mult)), 1); cons_assoc_set(env, symbol_intern("/"), gc_add(cfunc_new(div)), 1); cons_assoc_set(env, symbol_intern("mod"), gc_add(cfunc_new(mod)), 1); }
static pobject mult(pobject env, pobject params) { float result = 1; while (is_cons(params)) { pobject o = eval(env, cons_car(params)); if (is_number(o)) result *= number_value(o); params = cons_cdr(params); } return gc_add(number_new(result)); }
NUMBER number_from_string(char *str) { NUMBER num; int i; num = number_new(); if (*str == '-') { num.negative = 1; str++; } for (i = 0; str[i]; i++) number_insert_low(&num, str[i] - 0x30); return num; }
tm_obj _load(char* fname){ FILE* fp = fopen(fname, "rb"); if( fp == NULL ){ tm_raise("load: can not open file \"@\"", str_new(fname, strlen(fname))); return obj_none; } long len = _get_file_rest_len(fp); if(len > MAX_FILE_SIZE ){ tm_raise("load: file too big to load, size = @", number_new(len)); return obj_none; } tm_obj text = str_new(NULL, len); char* s = get_str(text); fread(s, len, 1, fp); fclose(fp); return text; }
static pobject div(pobject env, pobject params) { float result = 0; pobject o = eval(env, cons_car(params)); if (is_number(o)) { result = number_value(o); params = cons_cdr(params); if (is_cons(params)) { while (is_cons(params)) { pobject o = eval(env, cons_car(params)); if (is_number(o)) result /= number_value(o); /* TODO: division by zero error handling */ params = cons_cdr(params); } } } return gc_add(number_new(result)); }
NUMBER number_subtract(NUMBER num1, NUMBER num2) { int borrow, sub, i, j, flip; NUMBER tmp, res = number_new(); if (num2.negative) { num2.negative = 0; return number_add(num1, num2); } if (num1.negative) { num1.negative = 0; res = number_add(num2, num1); res.negative = 1; return res; } flip = !number_greater(num1, num2); if (flip) { tmp = num1; num1 = num2; num2 = tmp; } for (i = sub = borrow = 0; i < num1.numbers || i < num2.numbers || borrow; i++, sub = 0) { if (num2.numbers > i) sub = num2.number[i]; sub += borrow; if (num1.numbers > i) { num1.number[i] -= sub; for (j = 0; num1.number[i] < 0; j++, num1.number[i] += 10); number_insert_high(&res, num1.number[i]); borrow = j; } else { number_insert_high(&res, sub % 10); borrow = sub / 10; } } if (flip) res.negative = 1; return res; }
static pobject minus(pobject env, pobject params) { float result = 0; pobject o = eval(env, cons_car(params)); if (is_number(o)) { result = number_value(o); params = cons_cdr(params); if (is_cons(params)) { while (is_cons(params)) { pobject o = eval(env, cons_car(params)); if (is_number(o)) result -= number_value(o); params = cons_cdr(params); } } else { result = -result; } } return gc_add(number_new(result)); }
tm_obj tm_mul( tm_obj a, tm_obj b){ if( a.type == b.type && a.type == TM_NUM){ return number_new( get_num(a) * get_num(b) ); } if( a.type == TM_NUM && b.type == TM_STR){ tm_obj temp = a; a = b; b = temp; } if( a.type == TM_STR && b.type == TM_NUM){ if( get_str_len(a) == 0) return a; tm_obj str = str_new(NULL, get_int(b) * get_str_len(a) ); char* s = get_str(str); int i;for(i = 0; i < get_str_len(str) ; i+= get_str_len(a)){ memcpy( s + i , get_str(a), get_str_len(a)); } return str; } tm_raise("tm_mul: can not mul @ and @", a,b ); return obj_none; }
tm_obj tm_and( tm_obj a, tm_obj b){ return number_new(_tm_bool(a) && _tm_bool(b)); }
tm_obj tm_has(tm_obj a, tm_obj b){ return number_new( _tm_has(a, b)); }
tm_obj tm_not_equals( tm_obj a, tm_obj b){ return number_new(!tm_eq(a,b)); }
tm_obj t_tm_equals(tm_obj a, tm_obj b){ return number_new( tm_eq(a,b)); }
tm_obj tm_or( tm_obj a, tm_obj b){ return number_new(_tm_bool(a) || _tm_bool(b)); }
tm_obj tm_mtime(tm_obj p){ char const *s = get_str_arg(p, 0); struct stat stbuf; if (!stat(s,&stbuf)) { return number_new(stbuf.st_mtime); } tm_raise("tm_mtime(%s)",s); }