/* Copyright 2015 Ian Jauslin Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "number.h" #include #include #include #include // define MPFR_USE_VA_LIST to enable the use of mpfr_inits and mpfr_clears #define MPFR_USE_VA_LIST #include #include "istring.h" #include "definitions.cpp" #include "tools.h" #include "rational.h" #include "array.h" // init int init_Number(Number* number, int memory){ (*number).scalars=calloc(memory,sizeof(Q)); (*number).base=calloc(memory,sizeof(int)); (*number).memory=memory; (*number).length=0; return(0); } int free_Number(Number number){ free(number.scalars); free(number.base); return(0); } // copy int number_cpy(Number input, Number* output){ init_Number(output,input.length); number_cpy_noinit(input,output); return(0); } int number_cpy_noinit(Number input, Number* output){ int i; if((*output).memory=(*output).memory){ number_resize(output,2*(*output).memory); } (*output).scalars[(*output).length]=scalar; (*output).base[(*output).length]=base; (*output).length++; // not optimal number_sort(*output,0,(*output).length-1); return(0); } // concatenate int number_concat(Number input, Number* output){ int i; int offset=(*output).length; if((*output).length+input.length>(*output).memory){ // make it longer than needed by (*output).length (for speed) number_resize(output,2*(*output).length+input.length); } for(i=0;i=0){ (*inout).scalars[index]=Q_add((*inout).scalars[index], scalar); } else{ number_append(scalar, base, inout); } return(0); } // create a new number int number_add(Number x1, Number x2, Number* out){ number_cpy(x1,out); number_add_chain(x2,out); return(0); } // return the number Number number_add_ret(Number x1, Number x2){ Number out; number_add(x1,x2,&out); return(out); } // multiply int number_prod(Number x1, Number x2, Number* out){ int i,j; int div; Q new_scalar; int new_base; init_Number(out, x1.length); for(i=0;i0){ (*inout).scalars[i]=Q_inverse((*inout).scalars[i]); (*inout).scalars[i].denominator*=(*inout).base[i]; } else if((*inout).base[i]<0){ (*inout).scalars[i]=Q_inverse((*inout).scalars[i]); (*inout).scalars[i].denominator*=-(*inout).base[i]; (*inout).scalars[i].numerator*=-1; } else{ fprintf(stderr,"error: attempting to invert 0\n"); exit(-1); } } return(0); } // write to output int number_inverse(Number input, Number* output){ number_cpy(input,output); number_inverse_inplace(output); return(0); } // return result Number number_inverse_ret(Number x){ Number ret; number_inverse(x,&ret); return(ret); } // quotient int number_quot(Number x1, Number x2, Number* output){ Number inv; number_inverse(x2, &inv); number_prod(x1, inv, output); free_Number(inv); return(0); } int number_quot_chain(Number x1, Number* inout){ number_inverse_inplace(inout); number_prod_chain(x1, inout); return(0); } Number number_quot_ret(Number x1, Number x2){ Number ret; number_quot(x1, x2, &ret); return(ret); } // remove 0's int number_simplify(Number in, Number* out){ int i; init_Number(out, in.length); for(i=0;i0){ char_array_snprintf(out," + "); } if(simp.length>1 || (simp.length==1 && simp.base[0]!=1)){ char_array_append('(',out); } Q_sprint(simp.scalars[i], out); if(simp.length>1 || (simp.length==1 && simp.base[0]!=1)){ char_array_append(')',out); } if(simp.base[i]!=1){ char_array_snprintf(out,"s{%d}",simp.base[i]); } } free_Number(simp); return(0); } // print to stdout int number_print(Number number){ Char_Array buffer; init_Char_Array(&buffer,5*number.length); number_sprint(number, &buffer); printf("%s",buffer.str); return(0); } #define PP_NULL_MODE 0 #define PP_NUM_MODE 1 #define PP_SQRT_MODE 2 // read from a string int str_to_Number(char* str, Number* number){ char* ptr; int mode; char* buffer=calloc(str_len(str)+1,sizeof(char)); char* buffer_ptr=buffer; Q num; int base; // whether there are parentheses in the string int exist_parenthesis=0; init_Number(number, NUMBER_SIZE); // init num and base // init to 0 so that if str is empty, then the number is set to 0 num=quot(0,1); base=1; mode=PP_NULL_MODE; for(ptr=str;*ptr!='\0';ptr++){ switch(*ptr){ // read number case '(': if(mode==PP_NULL_MODE){ // init base base=1; mode=PP_NUM_MODE; exist_parenthesis=1; } break; case ')': if(mode==PP_NUM_MODE){ str_to_Q(buffer,&num); buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_NULL_MODE; } break; // read sqrt case '{': // init num if(num.numerator==0){ num=quot(1,1); } if(mode==PP_NULL_MODE){ mode=PP_SQRT_MODE; } // if there is a square root, then do not read a fraction (see end of loop) exist_parenthesis=1; break; case '}': if(mode==PP_SQRT_MODE){ sscanf(buffer,"%d",&base); buffer_ptr=buffer; *buffer_ptr='\0'; mode=PP_NULL_MODE; } break; // write num case '+': if(mode==PP_NULL_MODE){ number_add_elem(num, base, number); // re-init num and base num=quot(0,1); base=1; } break; default: if(mode!=PP_NULL_MODE){ buffer_ptr=str_addchar(buffer_ptr,*ptr); } break; } } // last step if(mode==PP_NULL_MODE){ if(exist_parenthesis==0){ str_to_Q(str, &num); } number_add_elem(num, base, number); } free(buffer); return(0); } // with Char_Array input int char_array_to_Number(Char_Array cstr_num,Number* output){ char* buffer; char_array_to_str(cstr_num,&buffer); str_to_Number(buffer, output); free(buffer); return(0); } // -------------------- Number_Matrix --------------------- // init int init_Number_Matrix(Number_Matrix* matrix, int length){ int i,j; (*matrix).matrix=calloc(length,sizeof(Number*)); (*matrix).indices=calloc(length,sizeof(int)); for(i=0;i