Posted to tcl by sebres at Thu Aug 29 14:15:30 GMT 2019view pretty
/* * tclfastinvsqrt.c -- * * Test module to get native handle of channel. * * Compile: * mingw: gcc -O2 -DUSE_TCL_STUBS=1 -I$tcl/win -I$tcl/generic tclfastinvsqrt.c -shared -o tclfastinvsqrt.dll libtclstub86.a * *nix: gcc -O2 -DUSE_TCL_STUBS=1 -I$tcl/unix -I$tcl/generic tclfastinvsqrt.c -shared -o tclfastinvsqrt.so libtclstub86.a * * Usage: * $ tclsh86 * % load tclfastinvsqrt * % expr {invsqrt(10)} */ #include "tcl.h" static inline double FastInvSqrt(double x, int accuracy) { char *buf = (char *)&x; double xhalf = 0.5f * x; Tcl_WideInt i = *(Tcl_WideInt*)buf; i = 0x5fe6eb50c7b537a9 - (i >> 1); buf = (char *)&i; x = *(double*)buf; while (accuracy--) { x = x*(1.5-(xhalf*x*x)); } return x; } int FastInvSqrtCmd( ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj * const objv[] ) { double dbl; int accuracy = 4; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "value ?accuracy?"); return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, objv[1], &dbl) != TCL_OK) { return TCL_ERROR; } if (objc > 2 && Tcl_GetIntFromObj(interp, objv[2], &accuracy) != TCL_OK) { return TCL_ERROR; } dbl = FastInvSqrt(dbl, accuracy); Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dbl)); return TCL_OK; } int Tclfastinvsqrt_Init(Tcl_Interp *interp) { if (!Tcl_InitStubs(interp, "8.5", 0)) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "::tcl::mathfunc::invsqrt", FastInvSqrtCmd, NULL, NULL); return TCL_OK; } /* load tclfastinvsqrt # speed vs accuracy: set tm 500 for {set x 2} {$x < 100000} {set x [expr {$x * 10}]} { puts $x:\t[timerate { expr { 1 / sqrt($x) } } $tm] puts \t[timerate { expr { invsqrt($x,1) } } $tm] puts \t[timerate { expr { invsqrt($x) } } $tm] } # accuracy : for {set x 2} {$x < 100000} {set x [expr {$x * 10}]} { puts $x:\t[expr { 1 / sqrt($x) }] puts \t[expr { invsqrt($x) }] } for {set x 2} {$x < 100000} {set x [expr {$x * 10}]} { puts $x:\t[expr { 1 / sqrt($x) }] puts \t[expr { invsqrt($x,1) }] } # Herbie example: for {set x 2} {$x < 100000} {set x [expr {$x * 10}]} { puts $x:\t[expr { sqrt($x+1) - sqrt($x) }] puts \t[expr { 1 / (sqrt($x+1) + sqrt($x)) }] puts \t[expr { invsqrt( (2*$x + 1 + 2/invsqrt(($x+1)*$x)) ) }] } */
Comments
Posted by sebres at Thu Aug 29 15:02:08 GMT 2019 [text] [code]
the comments about channel was copy&paste, simply ignore it :)