From aa0f3ae2988d372b190b9bde2e75a6d17e744e93 Mon Sep 17 00:00:00 2001 From: Ian Jauslin Date: Sun, 14 Jun 2015 00:52:45 +0000 Subject: Initial commit --- src/number.c | 551 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 551 insertions(+) create mode 100644 src/number.c (limited to 'src/number.c') diff --git a/src/number.c b/src/number.c new file mode 100644 index 0000000..5d4cd18 --- /dev/null +++ b/src/number.c @@ -0,0 +1,551 @@ +/* +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 "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