float dotProduct(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { float p0 = fpmul(x0,y0); float p1 = fpmul(x1,y1); float p2 = fpmul(x2,y2); float p3 = fpmul(x3,y3); float result = fpadd(fpadd(p0 , p1) , fpadd(p2 , p3)); return(result); }
void fp2inv_mont(f2elm_t *a) {// GF(p^2) inversion using Montgomery arithmetic, a = (a0-i*a1)/(a0^2+a1^2). f2elm_t t1; fpsqr_mont(a->e[0], t1.e[0]); // t10 = a0^2 fpsqr_mont(a->e[1], t1.e[1]); // t11 = a1^2 fpadd(t1.e[0], t1.e[1], t1.e[0]); // t10 = a0^2+a1^2 fpinv_mont(t1.e[0]); // t10 = (a0^2+a1^2)^-1 fpneg(a->e[1]); // a = a0-i*a1 fpmul_mont(a->e[0], t1.e[0], a->e[0]); fpmul_mont(a->e[1], t1.e[0], a->e[1]); // a = (a0-i*a1)*(a0^2+a1^2)^-1 }
enum RPNError rpn_run(byte *rpnExpr, word rpnLen, Float *yValue, Float *xValue) { rpnStackIndex = 0; word reader = 0; while (reader < rpnLen) { byte op = rpnExpr[reader++]; switch (op) { case RPN_VAR: // put a copy of the independent variable's value on rpnStack if (rpnStackIndex == RPN_STACK_SIZE) return RPN_ERR_OVERFLOW; rpn_push(xValue); break; case RPN_FUNC: { if (rpnStackIndex < 1) return RPN_ERR_UNDERFLOW; fp0load(rpn_get(rpnStackIndex - 1)); byte funcIndex = rpnExpr[reader++]; if (funcIndex == UNKNOWN_FUNCTION_INDEX) { --reader; return RPN_ERR_INVALID_FUNC; } // Check the argument (FP0). void *check = knownFunctions[funcIndex].checkArgFuncPtr; if (check) { enum RPNError e = (*check)(); // check FP0 if (e != RPN_ERR_NONE) return e; } // Argument (FP0) is valid. Apply the function to it. (*knownFunctions[funcIndex].evalFuncPtr)(); --rpnStackIndex; rpn_push(FP0ADDR); // push the result break; } case RPN_NUM: // put FP that follows on rpnStack if (rpnStackIndex == RPN_STACK_SIZE) return RPN_ERR_OVERFLOW; rpn_push((Float *) (rpnExpr + reader)); // push 6-byte accumulator reader += sizeof(Float); break; case RPN_ADD: case RPN_SUB: case RPN_MUL: if (rpnStackIndex < 2) return RPN_ERR_UNDERFLOW; fp0load(rpn_get(rpnStackIndex - 2)); fp1load(rpn_get(rpnStackIndex - 1)); switch (op) { case RPN_ADD: fpadd(); break; case RPN_SUB: fpsub(); break; case RPN_MUL: fpmul(); break; } rpnStackIndex -= 2; rpn_push(FP0ADDR); // push the result break; case RPN_DIV: { if (rpnStackIndex < 2) return RPN_ERR_UNDERFLOW; // Check if the divisor is too close to zero Float *divisor = rpn_get(rpnStackIndex - 1); fp0load(divisor); fpabs(); if (fpcmp(&verySmall) < 0) // if abs(divisor) too small return RPN_ERR_DIV_BY_ZERO; // avoid enormous (and unusable) quotient fp0load(divisor); fp1load(rpn_get(rpnStackIndex - 2)); // dividend fpdiv(); rpnStackIndex -= 2; rpn_push(FP0ADDR); // push the result break; } case RPN_NEG: if (rpnStackIndex < 1) return RPN_ERR_UNDERFLOW; fp0load(rpn_get(rpnStackIndex - 1)); fpneg(); --rpnStackIndex; rpn_push(FP0ADDR); // push the result break; case RPN_POW: if (rpnStackIndex < 2) return RPN_ERR_UNDERFLOW; fp0load(rpn_get(rpnStackIndex - 1)); // power fp1load(rpn_get(rpnStackIndex - 2)); // base if (fp1sgn() < 0 && ! fpisint()) // if negative base and non-int power return RPN_ERR_POW_OF_NEG; fppow(); rpnStackIndex -= 2; rpn_push(FP0ADDR); // push the result break; default: --reader; return RPN_ERR_UNEXPECTED; } } if (rpnStackIndex != 1) return RPN_ERR_INVALID_EXPR; #if 0 fp0load(rpn_get(0)); char buf[FPSTRBUFSIZ]; char *decimalResult = fpstr(buf); printf("Result: [%s]\n", decimalResult); #endif fpcpy(yValue, rpn_get(0)); return RPN_ERR_NONE; }
__inline void fp2add(const f2elm_t *a, const f2elm_t *b, f2elm_t *c) { // GF(p^2) addition, c = a+b in GF(p^2). fpadd(a->e[0], b->e[0], c->e[0]); fpadd(a->e[1], b->e[1], c->e[1]); }