def single_segment_expect_pv(expect, raw=True): """ Compute p-value for an expect value of a single high scoring segment. Prob(E >= x) ~ 1 - exp(-E) This function is equivalent to single_segment_score_pv as long as identical units (log) are used to compute scores and expect :param expect: :param raw: return raw P-value instead of -log10(pv) :return: """ with mpm.workprec(NUM_PREC_KA_PV): x = mpm.convert(expect) complement = mpm.convert('1') res = mpm.fsub(complement, mpm.exp(mpm.fneg(x))) if not raw: res = mpm.fneg(mpm.log10(res)) res = float(res) return res
def single_segment_score_pv(score, raw=True): """ Compute p-value for normalized local score of a single high scoring segment. Computes formula [1] in Karlin & Altschul, PNAS 1993 Prob(S' >= x) ~ 1 - exp(-exp(-x)) :param score: :param raw: return raw P-value instead of -log10(pv) :return: """ with mpm.workprec(NUM_PREC_KA_PV): x = mpm.convert(score) complement = mpm.convert('1') exponent = mpm.fneg(mpm.exp(mpm.fneg(x))) res = mpm.fsub(complement, mpm.exp(exponent)) if not raw: res = mpm.fneg(mpm.log10(res)) res = float(res) # Equivalent implementation using Python standard library: # # x = score # res = 1 - math.exp(-math.exp(-x)) # if not raw: # res = -1 * math.log10(res) return res
def findNthPolygonalNumber( n, k ): if real_int( k ) < 3: raise ValueError( 'the number of sides of the polygon cannot be less than 3,' ) return nint( fdiv( fsum( [ sqrt( fsum( [ power( k, 2 ), fprod( [ 8, k, real( n ) ] ), fneg( fmul( 8, k ) ), fneg( fmul( 16, n ) ), 16 ] ) ), k, -4 ] ), fmul( 2, fsub( k, 2 ) ) ) )
def findPolygonalNumber(n, k): return floor( fdiv( fsum([ sqrt( fsum([ power(k, 2), fprod([8, k, n]), fneg(fmul(8, k)), fneg(fmul(16, n)), 16 ])), k, -4 ]), fmul(2, fsub(k, 2))))
def getRight( args, count ): result = [ ] if isinstance( count, list ): for i in count: result.append( [ j for j in args ][ int( fneg( i ) ) : ] ) else: result.append( [ j for j in args ][ int( fneg( count ) ) : ] ) if len( result ) == 1: return result[ 0 ] else: return result
def getRightOperator( args, count ): result = [ ] if isinstance( count, list ): for i in count: result.append( args[ int( fneg( i ) ) : ] ) else: result.append( args[ int( fneg( count ) ) : ] ) if len( result ) == 1: return result[ 0 ] return result
def multi_segment_score_pv(score, num_segments, raw=True): """ Compute p-value for normalized score when considering multiple high scoring segments. This functions considers the normalized score Sr', i.e., the normalized score of the HSP at rank r. For r=1, this formula is equivalent to single_segment_score_pv Computes formula [3] in Karlin & Altschul, PNAS 1993 Prob(Sr' >= x) ~ 1 - exp(-exp(-x)) * SUM (k=0 ... r - 1) { exp(-kx) / k! } Implementation detail: Python's range is not right-inclusive, go up to r, not r - 1 for summation :param score: :param num_segments: :param raw: return raw P-value instead of -log10(pv) :return: """ with mpm.workprec(NUM_PREC_KA_PV): def create_summand(sum_x, k): prec_k = mpm.convert(k) enum = mpm.exp(mpm.fneg(mpm.fmul(prec_k, sum_x))) denom = mpm.factorial(prec_k) summand = mpm.fdiv(enum, denom) return summand x = mpm.convert(score) r = num_segments complement = mpm.convert('1') factor1 = mpm.exp(mpm.fneg(mpm.exp(mpm.fneg(x)))) factor2 = mpm.fsum(map(lambda k: create_summand(x, k), range(0, r))) res = mpm.fsub(complement, mpm.fmul(factor1, factor2)) if not raw: res = mpm.fneg(mpm.log10(res)) res = float(res) # Equivalent implementation using Python standard library: # # x = score # r = num_segments # factor_1 = math.exp(-math.exp(-x)) # factor_2 = math.fsum(map(lambda k: math.exp(-k * x) / math.factorial(k), range(0, r))) # res = 1 - factor_1 * factor_2 # if not raw: # res = -1 * math.log10(res) return res
def solveQuadraticPolynomial( a, b, c ): if a == 0: if b == 0: raise ValueError( 'invalid expression, no variable coefficients' ) else: # linear equation, one root return [ fdiv( fneg( c ), b ) ] else: d = sqrt( fsub( power( b, 2 ), fmul( 4, fmul( a, c ) ) ) ) x1 = fdiv( fadd( fneg( b ), d ), fmul( 2, a ) ) x2 = fdiv( fsub( fneg( b ), d ), fmul( 2, a ) ) return [ x1, x2 ]
def calculateWindChillOperator( measurement1, measurement2 ): ''' https://www.ibiblio.org/units/dictW.html ''' validUnitTypes = [ [ 'velocity', 'temperature' ], ] arguments = matchUnitTypes( [ measurement1, measurement2 ], validUnitTypes ) if not arguments: raise ValueError( '\'wind_chill\' requires velocity and temperature measurements' ) windSpeed = arguments[ 'velocity' ].convert( 'miles/hour' ).value temperature = arguments[ 'temperature' ].convert( 'degrees_F' ).value if windSpeed < 3: raise ValueError( '\'wind_chill\' is not defined for wind speeds less than 3 mph' ) if temperature > 50: raise ValueError( '\'wind_chill\' is not defined for temperatures over 50 degrees fahrenheit' ) result = fsum( [ 35.74, fmul( temperature, 0.6215 ), fneg( fmul( 35.75, power( windSpeed, 0.16 ) ) ), fprod( [ 0.4275, temperature, power( windSpeed, 0.16 ) ] ) ] ) # in case someone puts in a silly velocity if result < -459.67: result = -459.67 return RPNMeasurement( result, 'degrees_F' ).convert( arguments[ 'temperature' ].units )
def create_from_point_vector(normal_vector: Vector, point: Point): d = normal_vector.dot(Vector.convert_point(point)) plane_params = [ normal_vector.x, normal_vector.y, normal_vector.z, mpmath.fneg(d) ] return Plane(plane_params)
def subtract( self, time ): if isinstance( time, RPNMeasurement ): kneg = RPNMeasurement( fneg( time.getValue( ) ), time.getUnits( ) ) return self.add( kneg ) elif isinstance( time, RPNDateTime ): if self > time: delta = self - time factor = 1 else: delta = time - self factor = -1 if delta.days != 0: result = RPNMeasurement( delta.days * factor, 'day' ) result = result.add( RPNMeasurement( delta.seconds * factor, 'second' ) ) result = result.add( RPNMeasurement( delta.microseconds * factor, 'microsecond' ) ) elif delta.seconds != 0: result = RPNMeasurement( delta.seconds * factor, 'second' ) result = result.add( RPNMeasurement( delta.microseconds * factor, 'microsecond' ) ) else: result = RPNMeasurement( delta.microseconds * factor, 'microsecond' ) return result else: raise ValueError( 'incompatible type for subtracting from an absolute time' )
def solveQuadraticPolynomial( a, b, c ): '''This function applies the quadratic formula to solve a polynomial with coefficients of a, b, and c.''' if a == 0: if b == 0: raise ValueError( 'invalid expression, no variable coefficients' ) else: # linear equation, one root return [ fdiv( fneg( c ), b ) ] else: d = sqrt( fsub( power( b, 2 ), fmul( 4, fmul( a, c ) ) ) ) x1 = fdiv( fadd( fneg( b ), d ), fmul( 2, a ) ) x2 = fdiv( fsub( fneg( b ), d ), fmul( 2, a ) ) return [ x1, x2 ]
def testAllConversions( unitTypeTable, unitConversionMatrix ): print( 'Testing all conversions for consistency...' ) print( ) validated = 0 for unitType, unitList in unitTypeTable.items( ): for unit1, unit2, unit3 in itertools.permutations( unitList, 3 ): try: factor1 = unitConversionMatrix[ unit1, unit2 ] factor2 = unitConversionMatrix[ unit2, unit3 ] factor3 = unitConversionMatrix[ unit1, unit3 ] except: continue epsilon = power( 10, fneg( validationPrecision ) ) if not almosteq( fmul( factor1, factor2 ), factor3, rel_eps=epsilon ): print( 'conversion inconsistency found for ' + unit1 + ', ' + unit2 + ', and', unit3, file=sys.stderr ) print( unit1 + ' --> ' + unit2, factor1, file=sys.stderr ) print( unit2 + ' --> ' + unit3, factor2, file=sys.stderr ) print( unit3 + ' --> ' + unit1, factor3, file=sys.stderr ) print( ) validated += 1 if validated % 1000 == 0: print( '\r' + '{:,} conversion permutations validated...'.format( validated ), end='' ) print( '\r' + '{:,} conversion permutations were validated to {:,} digits precision.'. \ format( validated, validationPrecision ) ) print( 'No consistency problems detected.' )
def getNthKFibonacciNumber( n, k ): if real( n ) < 0: raise ValueError( 'non-negative argument expected' ) if real( k ) < 2: raise ValueError( 'argument <= 2 expected' ) if n < k - 1: return 0 nth = int( n ) + 4 precision = int( fdiv( fmul( n, k ), 8 ) ) if ( mp.dps < precision ): mp.dps = precision poly = [ 1 ] poly.extend( [ -1 ] * int( k ) ) roots = polyroots( poly ) nthPoly = getNthFibonacciPolynomial( k ) result = 0 exponent = fsum( [ nth, fneg( k ), -2 ] ) for i in range( 0, int( k ) ): result += fdiv( power( roots[ i ], exponent ), polyval( nthPoly, roots[ i ] ) ) return floor( fadd( re( result ), fdiv( 1, 2 ) ) )
def calculateWindChill( measurement1, measurement2 ): validUnitTypes = [ [ 'velocity', 'temperature' ], ] arguments = matchUnitTypes( [ measurement1, measurement2 ], validUnitTypes ) if not arguments: raise ValueError( '\'wind_chill\' requires velocity and temperature measurements' ) wind_speed = arguments[ 'velocity' ].convert( 'miles/hour' ).value temperature = arguments[ 'temperature' ].convert( 'degrees_F' ).value if wind_speed < 3: raise ValueError( '\'wind_chill\' is not defined for wind speeds less than 3 mph' ) if temperature > 50: raise ValueError( '\'wind_chill\' is not defined for temperatures over 50 degrees fahrenheit' ) result = fsum( [ 35.74, fmul( temperature, 0.6215 ), fneg( fmul( 35.75, power( wind_speed, 0.16 ) ) ), fprod( [ 0.4275, temperature, power( wind_speed, 0.16 ) ] ) ] ) # in case someone puts in a silly velocity if result < -459.67: result = -459.67 return RPNMeasurement( result, 'degrees_F' ).convert( arguments[ 'temperature' ].units )
def gammaincc(a, x, dps=50, maxterms=10*10*10*10*10*10*10*10): """Compute gammaincc exactly like mpmath does but allow for more terms in hypercomb. See mpmath/functions/expintegrals.py#L187 in the mpmath github repository. """ with mp.workdps(dps): z, a = a, x if mp.isint(z): try: # mpmath has a fast integer path return mpf2float(mp.gammainc(z, a=a, regularized=True)) except mp.libmp.NoConvergence: pass nega = mp.fneg(a, exact=True) G = [z] # Use 2F0 series when possible; fall back to lower gamma representation try: def h(z): r = z-1 return [([mp.exp(nega), a], [1, r], [], G, [1, -r], [], 1/nega)] return mpf2float(mp.hypercomb(h, [z], force_series=True)) except mp.libmp.NoConvergence: def h(z): T1 = [], [1, z-1], [z], G, [], [], 0 T2 = [-mp.exp(nega), a, z], [1, z, -1], [], G, [1], [1+z], a return T1, T2 return mpf2float(mp.hypercomb(h, [z], maxterms=maxterms))
def subtract(self, time): if isinstance(time, RPNMeasurement): kneg = RPNMeasurement(fneg(time.value), time.units) return self.add(kneg) elif isinstance(time, RPNDateTime): if self > time: delta = self - time factor = 1 else: delta = time - self factor = -1 if delta.days != 0: result = RPNMeasurement(delta.days * factor, 'day') result = result.add( RPNMeasurement(delta.seconds * factor, 'second')) result = result.add( RPNMeasurement(delta.microseconds * factor, 'microsecond')) elif delta.seconds != 0: result = RPNMeasurement(delta.seconds * factor, 'second') result = result.add( RPNMeasurement(delta.microseconds * factor, 'microsecond')) else: result = RPNMeasurement(delta.microseconds * factor, 'microsecond') return result else: raise ValueError( 'incompatible type for subtracting from an absolute time')
def gammaincc(a, x, dps=50, maxterms=10**8): """Compute gammaincc exactly like mpmath does but allow for more terms in hypercomb. See mpmath/functions/expintegrals.py#L187 in the mpmath github repository. """ with mp.workdps(dps): z, a = a, x if mp.isint(z): try: # mpmath has a fast integer path return mpf2float(mp.gammainc(z, a=a, regularized=True)) except mp.libmp.NoConvergence: pass nega = mp.fneg(a, exact=True) G = [z] # Use 2F0 series when possible; fall back to lower gamma representation try: def h(z): r = z-1 return [([mp.exp(nega), a], [1, r], [], G, [1, -r], [], 1/nega)] return mpf2float(mp.hypercomb(h, [z], force_series=True)) except mp.libmp.NoConvergence: def h(z): T1 = [], [1, z-1], [z], G, [], [], 0 T2 = [-mp.exp(nega), a, z], [1, z, -1], [], G, [1], [1+z], a return T1, T2 return mpf2float(mp.hypercomb(h, [z], maxterms=maxterms))
def calc_model_evidence(self): vval = 0 mp.mp.dps = 50 for action in range(self.hparams.num_actions): # val=1 # aa = self.a[action] # for i in xrange(int(self.a[action]-self.a0)): # aa-=1 # val*=aa # val/=(2.0*math.pi) # val/=self.b[action] # val*=gamma(aa) # val/=(self.b[action]**aa) # val *= np.sqrt(np.linalg.det(self.lambda_prior * np.eye(self.hparams.context_dim + 1)) / np.linalg.det(self.precision[action])) # val *= (self.b0 ** self.a0) # val/= gamma(self.a0) # vval += val #val= 1/float((2.0 * math.pi) ** (self.a[action]-self.a0)) #val*= (float(gamma(self.a[action]))/float(gamma(self.a0))) #val*= np.sqrt(float(np.linalg.det(self.lambda_prior * np.eye(self.hparams.context_dim + 1)))/float(np.linalg.det(self.precision[action]))) #val*= (float(self.b0**self.a0)/float(self.b[action]**self.a[action])) val= mp.mpf(mp.fmul(mp.fneg(mp.log(mp.fmul(2.0 , mp.pi))) , mp.fsub(self.a[action],self.a0))) val+= mp.loggamma(self.a[action]) val-= mp.loggamma(self.a0) val+= 0.5*mp.log(np.linalg.det(self.lambda_prior * np.eye(self.hparams.context_dim + 1))) val -= 0.5*mp.log(np.linalg.det(self.precision[action])) val+= mp.fmul(self.a0,mp.log(self.b0)) val-= mp.fmul(self.a[action],mp.log(self.b[action])) vval+=mp.exp(val) vval/=float(self.hparams.num_actions) return vval
def getECMFactors( target ): from pyecm import factors n = int( floor( target ) ) verbose = g.verbose randomSigma = True asymptoticSpeed = 10 processingPower = 1.0 if n < -1: return [ ( -1, 1 ) ] + getECMFactors( fneg( n ) ) elif n == -1: return [ ( -1, 1 ) ] elif n == 0: return [ ( 0, 1 ) ] elif n == 1: return [ ( 1, 1 ) ] if verbose: print( '\nfactoring', n, '(', int( floor( log10( n ) ) ), ' digits)...' ) if g.factorCache is None: loadFactorCache( ) if n in g.factorCache: if verbose and n != 1: print( 'cache hit:', n ) print( ) return g.factorCache[ n ] result = [ ] for factor in factors( n, verbose, randomSigma, asymptoticSpeed, processingPower ): result.append( factor ) result = [ int( i ) for i in result ] largeFactors = list( collections.Counter( [ i for i in result if i > 65535 ] ).items( ) ) product = int( fprod( [ power( i[ 0 ], i[ 1 ] ) for i in largeFactors ] ) ) save = False if product not in g.factorCache: g.factorCache[ product ] = largeFactors save = True result = list( collections.Counter( result ).items( ) ) if n > g.minValueToCache and n not in g.factorCache: g.factorCache[ n ] = result g.factorCacheIsDirty = True if verbose: print( ) return result
def getNthGeneralizedPolygonalNumber(n, k): negative = (fmod(n, 2) == 0) n = floor(fdiv(fadd(n, 1), 2)) if negative: n = fneg(n) return getNthPolygonalNumber(n, k)
def test_analyzed_incdecfunc_increasing(analyzed_incdecfunc): """Test FuncIntervals' increasing() and decreasing() methods.""" analyzed_incdecfunc_increasing = analyzed_incdecfunc.increasing typechecking.typecheck_intervals(analyzed_incdecfunc_increasing) testing_utils.mpf_assert_allclose( analyzed_incdecfunc_increasing, [(mp.fneg(mp.e), -0.001)], constants.EPSILON1 / 10, )
def create_from_3points(points): vec_a = Vector.create_from_points(points[0], points[1]) vec_b = Vector.create_from_points(points[0], points[2]) normal_vector = vec_a.cross(vec_b) d = normal_vector.dot(Vector.convert_point(points[2])) plane_params = [ normal_vector.a, normal_vector.b, normal_vector.c, mpmath.fneg(d) ] return Plane(plane_params)
def solveQuadraticPolynomial( a, b, c ): # pylint: disable=invalid-name ''' This function applies the quadratic formula to solve a polynomial with coefficients of a, b, and c. ''' if a == 0: if b == 0: raise ValueError( 'invalid expression, no variable coefficients' ) # linear equation, one root return [ fdiv( fneg( c ), b ) ] else: d = sqrt( fsub( power( b, 2 ), fmul( 4, fmul( a, c ) ) ) ) x1 = fdiv( fadd( fneg( b ), d ), fmul( 2, a ) ) x2 = fdiv( fsub( fneg( b ), d ), fmul( 2, a ) ) return [ x1, x2 ]
def getFactors(target): if target < -1: result = [-1] result.extend(getFactors(fneg(target))) return result if target == -1: return [-1] if target == 0: return [0] if target == 1: return [1] n = int(floor(target)) setAccuracy(floor(fadd(log10(n), 2))) if g.factorCache is None: loadFactorCache() if not g.ignoreCache: if n in g.factorCache: if g.verbose and n != 1: print('cache hit:', n) print() debugPrint('\nfactor cache', n, g.factorCache[n]) return g.factorCache[n] try: result = factorByTrialDivision(n) # throws if n is too big if n > g.minValueToCache and n not in g.factorCache: g.factorCache[n] = result return result except ValueError: pass if g.useYAFU and n > g.minValueForYAFU: result = runYAFU(n) else: result = factorise(int(n)) if n > g.minValueToCache: if g.ignoreCache or (not g.ignoreCache and n not in g.factorCache): debugPrint('\ncaching factors of ', n, result) g.factorCache[n] = result return result
def getNthGeneralizedPolygonalNumber( n, k ): if real_int( k ) < 3: raise ValueError( 'the number of sides of the polygon cannot be less than 3,' ) negative = ( fmod( n, 2 ) == 0 ) n = floor( fdiv( fadd( n, 1 ), 2 ) ) if negative: n = fneg( n ) return getNthPolygonalNumber( n, k )
def summed_score_pv(sum_score, num_segments, raw=True): """ Compute p-value over sum of scores for top r segments. As opposed to multi_segment_pv, this considers the total sum of scores for the top r scoring segments together. Computes formula [5] in Karlin & Altschul, PNAS 1993 Prob(Tr >= x) ~ exp(-x) * x**(r-1) / r! * (r - 1)! where Tr = S1' + ... + Sr' is the sum over the normalized scores of the top r segments :param sum_score: :param num_segments: :param raw: return raw P-value instead of -log10(pv) :return: """ with mpm.workprec(NUM_PREC_KA_PV): x = mpm.convert(sum_score) r = mpm.convert(str(num_segments)) rm1 = mpm.fsub(r, mpm.convert('1')) enum = mpm.fmul(mpm.exp(mpm.fneg(x)), mpm.power(x, rm1)) denom = mpm.fmul(mpm.factorial(r), mpm.factorial(rm1)) res = mpm.fdiv(enum, denom) if not raw: res = mpm.fneg(mpm.log10(res)) res = float(res) # Equivalent implementation using Python standard library: # # r = num_segments # x = sum_score # enum = math.exp(-x) * math.pow(x, (r - 1)) # denom = math.factorial(r) * math.factorial(r - 1) # res = enum / denom # if not raw: # res = -1 * math.log10(res) return res
def rotateDigitsRight(n, k): if k < 0: return rotateDigitsLeft(n, fneg(k)) n = getMPFIntegerAsString(n) if k > len(n): fmod(k, len(n)) rotate = int(k) n = n[-rotate:] + n[:-rotate] return mpmathify(n)
def convertToSpecialBase( value, baseFunction, outputBaseDigits = False, numerals = g.defaultNumerals ): ''' This version supports arbitrary non-constant bases. The place value is determined by the function passed in. The function takes a single argument which represents the place, and it returns the value that that place represents. As an example for base 10, the function would return 10^n for argument n. ''' if value == 0: return 0 if value < 0: return '-' + convertToBaseN( fneg( value ), base, outputBaseDigits, numerals ) if outputBaseDigits: result = [ ] else: result = '' positionValues = [ ] position = 1 positionValue = baseFunction( position ) while positionValue <= value: positionValues.append( positionValue ) position += 1 positionValue = baseFunction( position ) if outputBaseDigits: result = [ ] else: result = '' remaining = value while positionValues: base = positionValues.pop( ) digit = floor( fdiv( remaining, base ) ) if outputBaseDigits: result.append( digit ) else: result += numerals[ int( digit ) ] remaining = fsub( remaining, fmul( digit, base ) ) return result
def getNthAlternatingFactorial( n ): result = 0 negative = False for i in arange( real( n ), 0, -1 ): if negative: result = fadd( result, fneg( fac( i ) ) ) negative = False else: result = fadd( result, fac( i ) ) negative = True return result
def getFactors( target ): if target < -1: result = [ -1 ] result.extend( getFactors( fneg( target ) ) ) return result elif target == -1: return [ -1 ] elif target == 0: return [ 0 ] elif target == 1: return [ 1 ] n = int( floor( target ) ) if g.factorCache is None: loadFactorCache( ) if not g.ignoreCache: if n in g.factorCache: if g.verbose and n != 1: print( 'cache hit:', n ) print( ) debugPrint( '\nfactor cache', n, g.factorCache[ n ] ) return g.factorCache[ n ] try: result = factorByTrialDivision( n ) # throws if n is too big if n > g.minValueToCache and n not in g.factorCache: g.factorCache[ n ] = result return result except ValueError as error: pass if g.useYAFU and n > g.minValueForYAFU: result = runYAFU( n ) else: from rpn.factorise import factorise result = factorise( int( n ) ) if n > g.minValueToCache: if g.ignoreCache or ( not g.ignoreCache and n not in g.factorCache ): debugPrint( '\ncaching factors of ', n, result ) g.factorCache[ n ] = result return result
def test_analyzed_incdecfunc_decreasing(analyzed_incdecfunc): """Test accuracy of analyzed_incdecfunc.decreasing(). This works really well because in x_range, incdecfunc decreases across (-3, -e). Comparing with an irrational constant really pushes the boundaries of the precision of func_analysis. """ analyzed_incdecfunc_decreasing = analyzed_incdecfunc.decreasing typechecking.typecheck_intervals(analyzed_incdecfunc_decreasing) testing_utils.mpf_assert_allclose( analyzed_incdecfunc.decreasing, [(-3, mp.fneg(mp.e))], constants.EPSILON1 / 11, )
def convertToBaseN(value, base, outputBaseDigits=False, numerals=g.defaultNumerals): ''' This handles any integer base as long as there is a big-enough list of numerals to use. In practice this ends up being 0-9, a-z, and A-Z, which allows us to support up to base 62. ''' if outputBaseDigits: if base < 2: raise ValueError('base must be greater than 1') if value < 0: raise ValueError( '\'get_base_k_digits\' does not support negative numbers.') else: if not 2 <= base <= len(numerals): raise ValueError('base must be from 2 to {0}'.format( len(numerals))) if value == 0: return 0 if value < 0: return '-' + convertToBaseN(fneg(value), base, outputBaseDigits, numerals) if outputBaseDigits: result = [] else: result = '' leftDigits = mpmathify(value) while leftDigits > 0: modulo = fmod(leftDigits, base) if outputBaseDigits: result.insert(0, int(modulo)) else: result = numerals[int(modulo)] + result leftDigits = floor(fdiv(leftDigits, base)) return result
def gammainc(a, x, dps=50, maxterms=10**8): """Compute gammainc exactly like mpmath does but allow for more summands in hypercomb. See mpmath/functions/expintegrals.py#L134 in the mpmath github repository. """ with mp.workdps(dps): z, a, b = mp.mpf(a), mp.mpf(x), mp.mpf(x) G = [z] negb = mp.fneg(b, exact=True) def h(z): T1 = [mp.exp(negb), b, z], [1, z, -1], [], G, [1], [1 + z], b return (T1, ) res = mp.hypercomb(h, [z], maxterms=maxterms) return mpf2float(res)
def gammainc(a, x, dps=50, maxterms=10**8): """Compute gammainc exactly like mpmath does but allow for more summands in hypercomb. See mpmath/functions/expintegrals.py#L134 in the mpmath github repository. """ with mp.workdps(dps): z, a, b = mp.mpf(a), mp.mpf(x), mp.mpf(x) G = [z] negb = mp.fneg(b, exact=True) def h(z): T1 = [mp.exp(negb), b, z], [1, z, -1], [], G, [1], [1+z], b return (T1,) res = mp.hypercomb(h, [z], maxterms=maxterms) return mpf2float(res)
def testAllConversions(unitTypeTable, unitConversionMatrix): print('Testing all conversions for consistency...') print() validated = 0 for _, unitList in unitTypeTable.items(): for unit1, unit2, unit3 in itertools.permutations(unitList, 3): try: factor1 = unitConversionMatrix[unit1, unit2] factor2 = unitConversionMatrix[unit2, unit3] factor3 = unitConversionMatrix[unit1, unit3] except ValueError: continue epsilon = power(10, fneg(VALIDATION_PRECISION)) if not almosteq(fmul(factor1, factor2), factor3, rel_eps=epsilon): print('conversion inconsistency found for ' + unit1 + ', ' + unit2 + ', and', unit3, file=sys.stderr) print(unit1 + ' --> ' + unit2, factor1, file=sys.stderr) print(unit2 + ' --> ' + unit3, factor2, file=sys.stderr) print(unit3 + ' --> ' + unit1, factor3, file=sys.stderr) print() validated += 1 if validated % 1000 == 0: print('\r' + '{:,} conversion permutations validated...'.format( validated), end='') print( '\r' + '{:,} conversion permutations were validated to {:,} digits precision.', format(validated, VALIDATION_PRECISION)) print('No consistency problems detected.')
def getInvertedBits( n ): value = real_int( n ) # determine how many groups of bits we will be looking at if value == 0: groupings = 1 else: groupings = int( fadd( floor( fdiv( ( log( value, 2 ) ), g.bitwiseGroupSize ) ), 1 ) ) placeValue = mpmathify( 1 << g.bitwiseGroupSize ) multiplier = mpmathify( 1 ) remaining = value result = mpmathify( 0 ) for i in range( 0, groupings ): result = fadd( fmul( fsum( [ placeValue, fneg( fmod( remaining, placeValue ) ), -1 ] ), multiplier ), result ) remaining = floor( fdiv( remaining, placeValue ) ) multiplier = fmul( multiplier, placeValue ) return result
def convertToBaseN( value, base, outputBaseDigits=False, numerals=g.defaultNumerals ): ''' This handles any integer base as long as there is a big-enough list of numerals to use. In practice this ends up being 0-9, a-z, and A-Z, which allows us to support up to base 62. ''' if outputBaseDigits: if ( base < 2 ): raise ValueError( 'base must be greater than 1' ) else: if not ( 2 <= base <= len( numerals ) ): raise ValueError( 'base must be from 2 to {0}'.format( len( numerals ) ) ) if value == 0: return 0 if value < 0: return '-' + convertToBaseN( fneg( value ), base, outputBaseDigits, numerals ) if outputBaseDigits: result = [ ] else: result = '' leftDigits = mpmathify( value ) while leftDigits > 0: modulo = fmod( leftDigits, base ) if outputBaseDigits: result.insert( 0, int( modulo ) ) else: result = numerals[ int( modulo ) ] + result leftDigits = floor( fdiv( leftDigits, base ) ) return result
def handleOutput(valueList, indent=0, file=sys.stdout): ''' Once the evaluation of terms is complete, the results need to be translated into output. If the result is a list or a generator, special formatting turns those into text output. Date-time values and measurements also require special formatting. Setting file to an io.StringIO objects allows for 'printing' to a string, which is used by makeHelp.py to generate actual rpn output for the examples. ''' if valueList is None: return file indentString = ' ' * indent if len(valueList) != 1: if g.checkForSingleResults: print('valueList', valueList) raise ValueError('unexpected multiple results!') valueList = [valueList] if isinstance(valueList[0], RPNFunction): print(indentString + 'rpn: unexpected end of input in function definition', file=file) else: mp.pretty = True result = valueList.pop() if result is nan: return file if g.comma: g.integerGrouping = 3 # override whatever was set on the command-line g.leadingZero = False # this one, too g.integerDelimiter = ',' else: g.integerDelimiter = ' ' if isinstance(result, RPNGenerator): formatListOutput(result.getGenerator(), indent=indent, file=file) elif isinstance(result, list): formatListOutput(result, indent=indent, file=file) else: # single result if isinstance(result, RPNDateTime): outputString = formatDateTime(result) elif isinstance(result, str): result = checkForVariable(result) outputString = result else: # output the answer with all the extras according to command-line arguments # handle the units if we are displaying a measurement if isinstance(result, RPNMeasurement): outputString = formatOutput( nstr(result.value, g.outputAccuracy, min_fixed=-g.maximumFixed - 1)) outputString += ' ' + formatUnits(result) # handle a complex output (mpmath type: mpc) elif isinstance(result, mpc): #print( 'result', result, type( result ) ) #print( 'im', im( result ), type( im( result ) ) ) #print( 're', re( result ), type( re( result ) ) ) if im(result) > 0: outputString = '(' + formatOutput( nstr( mpmathify( re( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + \ ' + ' + formatOutput( nstr( mpmathify( im( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + 'j)' elif im(result) < 0: outputString = '(' + formatOutput( nstr( mpmathify( re( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + \ ' - ' + formatOutput( nstr( fneg( mpmathify( im( result ) ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + 'i)' else: outputString = formatOutput( nstr(re(result), g.outputAccuracy, min_fixed=-g.maximumFixed - 1)) # otherwise, it's a plain old mpf else: outputString = formatOutput( nstr(result, g.outputAccuracy, min_fixed=-g.maximumFixed - 1)) print(indentString + outputString, file=file) # handle --identify if g.identify: handleIdentify(result, file) saveResult(result) if g.timer or g.tempTimerMode: print('\n' + indentString + '{:.3f} seconds'.format( (time_ns() - g.startTime) / 1_000_000_000), file=file) return file
def handleOutput( valueList, indent=0, file=sys.stdout ): ''' Once the evaluation of terms is complete, the results need to be translated into output. If the result is a list or a generator, special formatting turns those into text output. Date-time values and measurements also require special formatting. Setting file to an io.StringIO objects allows for 'printing' to a string, which is used by makeHelp.py to generate actual rpn output for the examples. ''' if valueList is None: return file indentString = ' ' * indent if len( valueList ) != 1: if g.checkForSingleResults: print( 'valueList', valueList ) raise ValueError( 'unexpected multiple results!' ) valueList = [ valueList ] if isinstance( valueList[ 0 ], RPNFunction ): print( indentString + 'rpn: unexpected end of input in function definition', file=file ) else: mp.pretty = True result = valueList.pop( ) if result is nan: return file if g.comma: g.integerGrouping = 3 # override whatever was set on the command-line g.leadingZero = False # this one, too g.integerDelimiter = ',' else: g.integerDelimiter = ' ' if isinstance( result, RPNGenerator ): formatListOutput( result.getGenerator( ), indent=indent, file=file ) elif isinstance( result, list ): formatListOutput( result, indent=indent, file=file ) else: # single result if isinstance( result, RPNDateTime ): outputString = formatDateTime( result ) elif isinstance( result, str ): result = checkForVariable( result ) outputString = result else: # output the answer with all the extras according to command-line arguments # handle the units if we are displaying a measurement if isinstance( result, RPNMeasurement ): outputString = formatOutput( nstr( result.value, g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) outputString += ' ' + formatUnits( result ) # handle a complex output (mpmath type: mpc) elif isinstance( result, mpc ): #print( 'result', result, type( result ) ) #print( 'im', im( result ), type( im( result ) ) ) #print( 're', re( result ), type( re( result ) ) ) imaginary = im( result ) if im( result ) > 0: outputString = '(' + formatOutput( nstr( mpmathify( re( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + \ ' + ' + formatOutput( nstr( mpmathify( im( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + 'j)' elif im( result ) < 0: outputString = '(' + formatOutput( nstr( mpmathify( re( result ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + \ ' - ' + formatOutput( nstr( fneg( mpmathify( im( result ) ) ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) + 'i)' else: outputString = formatOutput( nstr( re( result ), g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) # otherwise, it's a plain old mpf else: outputString = formatOutput( nstr( result, g.outputAccuracy, min_fixed=-g.maximumFixed - 1 ) ) print( indentString + outputString, file=file ) # handle --identify if g.identify: handleIdentify( result, file ) saveResult( result ) if g.timer or g.tempTimerMode: print( '\n' + indentString + '{:.3f} seconds'.format( time.process_time( ) - g.startTime ), file=file )
def solveCubicPolynomial( a, b, c, d ): if mp.dps < 50: mp.dps = 50 if a == 0: return solveQuadraticPolynomial( b, c, d ) f = fdiv( fsub( fdiv( fmul( 3, c ), a ), fdiv( power( b, 2 ), power( a, 2 ) ) ), 3 ) g = fdiv( fadd( fsub( fdiv( fmul( 2, power( b, 3 ) ), power( a, 3 ) ), fdiv( fprod( [ 9, b, c ] ), power( a, 2 ) ) ), fdiv( fmul( 27, d ), a ) ), 27 ) h = fadd( fdiv( power( g, 2 ), 4 ), fdiv( power( f, 3 ), 27 ) ) # all three roots are the same if h == 0: x1 = fneg( root( fdiv( d, a ), 3 ) ) x2 = x1 x3 = x2 # two imaginary and one real root elif h > 0: r = fadd( fneg( fdiv( g, 2 ) ), sqrt( h ) ) if r < 0: s = fneg( root( fneg( r ), 3 ) ) else: s = root( r, 3 ) t = fsub( fneg( fdiv( g, 2 ) ), sqrt( h ) ) if t < 0: u = fneg( root( fneg( t ), 3 ) ) else: u = root( t, 3 ) x1 = fsub( fadd( s, u ), fdiv( b, fmul( 3, a ) ) ) real = fsub( fdiv( fneg( fadd( s, u ) ), 2 ), fdiv( b, fmul( 3, a ) ) ) imaginary = fdiv( fmul( fsub( s, u ), sqrt( 3 ) ), 2 ) x2 = mpc( real, imaginary ) x3 = mpc( real, fneg( imaginary ) ) # all real roots else: j = sqrt( fsub( fdiv( power( g, 2 ), 4 ), h ) ) k = acos( fneg( fdiv( g, fmul( 2, j ) ) ) ) if j < 0: l = fneg( root( fneg( j ), 3 ) ) else: l = root( j, 3 ) m = cos( fdiv( k, 3 ) ) n = fmul( sqrt( 3 ), sin( fdiv( k, 3 ) ) ) p = fneg( fdiv( b, fmul( 3, a ) ) ) x1 = fsub( fmul( fmul( 2, l ), cos( fdiv( k, 3 ) ) ), fdiv( b, fmul( 3, a ) ) ) x2 = fadd( fmul( fneg( l ), fadd( m, n ) ), p ) x3 = fadd( fmul( fneg( l ), fsub( m, n ) ), p ) return [ chop( x1 ), chop( x2 ), chop( x3 ) ]
def getNegative( n ): if isinstance( n, RPNMeasurement ): return RPNMeasurement( fneg( n.getValue( ) ), n.getUnits( ) ) else: return fneg( n )
def _getUpperBound(self, basic_value, coeff): if coeff >= mp.fneg(self.tolerance): return mp.inf else: return mp.fneg(mp.fdiv(basic_value, coeff))
def getNthPolygonalNumber( n, k ): if real_int( k ) < 3: raise ValueError( 'the number of sides of the polygon cannot be less than 3,' ) coeff = fdiv( fsub( k, 2 ), 2 ) return polyval( [ coeff, fneg( fsub( coeff, 1 ) ), 0 ], real( n ) )
def parseInputValue( term, inputRadix = 10 ): if isinstance( term, mpf ): return term possibleDate = True tCount = 0 # one 'T' is allowed in a date, but no other letters for c in term: if c.isalpha( ): if c == 'T': if tCount > 0: possibleDate = False break tCount += 1 else: possibleDate = False break if not g.interactive: if term[ 0 ] == '$' and term[ 1 : ] in g.userVariables: term = g.userVariables[ term[ 1 : ] ] return term if term[ 0 ] == '@' and term[ 1 : ] in g.userFunctions: term = g.userFunctions[ term[ 1 : ] ] return term if term[ 0 ] == "'": return term[ 1 : ] innerChars = term[ 1 : -1 ] # this helps us parse dates if '/' in innerChars and possibleDate: term = term.replace( '/', '-' ) innerChars = term[ 1 : -1 ] # 'e' implies scientific notation, which isn't a date regardless if possibleDate: # 'd' means a dice expression, '[' means a build_number expression, so don't treat it as a date if ( ( '-' in innerChars ) or ( ':' in innerChars ) ) and ( '[' not in term ): # try: datetime = arrow.get( term ) datetime = RPNDateTime( datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, datetime.microsecond ) # except: # raise ValueError( 'error parsing datetime' ) return datetime if term == '0': return mpmathify( 0 ) # ignore commas term = ''.join( [ i for i in term if i not in ',' ] ) if term[ 0 ] == '\\': term = term[ 1 : ] ignoreSpecial = True else: ignoreSpecial = False if inputRadix == 10: imaginary = term[ -1 ] in ( 'i', 'j' ) else: imaginary = False if imaginary: term = term[ : -1 ] if '.' in term: if inputRadix == 10: newPrecision = len( term ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) if imaginary: return mpc( imag = term ) else: return mpmathify( term ) decimal = term.find( '.' ) else: decimal = len( term ) negative = term[ 0 ] == '-' if negative: start = 1 else: if term[ 0 ] == '+': start = 1 else: start = 0 integer = term[ start : decimal ] mantissa = term[ decimal + 1 : ] # check for hex, then binary, then octal, otherwise a plain old decimal integer if not ignoreSpecial and mantissa == '': if integer[ 0 ] == '0': if len( integer ) == 1: return mpmathify( 0 ) if integer[ 1 ] in 'Xx': # set the precision big enough to handle this value newPrecision = math.ceil( ( math.log10( 16 ) * ( len( integer ) - 2 ) ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) return mpmathify( int( integer[ 2 : ], 16 ) ) elif integer[ -1 ] in 'bB': # set the precision big enough to handle this value newPrecision = math.ceil( math.log10( 2 ) * ( len( integer ) - 1 ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) integer = integer[ : -1 ] return mpmathify( int( integer, 2 ) * ( -1 if negative else 1 ) ) else: integer = integer[ 1 : ] return mpmathify( int( integer, 8 ) ) if integer[ 0 ] == '1' and integer[ -1 ] in 'bB': # set the precision big enough to handle this value newPrecision = math.ceil( math.log10( 2 ) * ( len( integer ) - 1 ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) integer = integer[ : -1 ] return mpmathify( int( integer, 2 ) * ( -1 if negative else 1 ) ) elif inputRadix == 10: newPrecision = len( integer ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) result = fneg( integer ) if negative else mpmathify( integer ) if imaginary: return mpc( real = '0.0', imag = result ) else: return result # finally, we have a non-radix 10 number with a mantissa to parse result = convertToBase10( integer, mantissa, inputRadix ) result = fneg( result ) if negative else mpmathify( result ) if imaginary: return mpc( real = '0.0', imag = result ) else: return result
def getCenteredPolygonalNumber( n, k ): if real_int( k ) < 3: raise ValueError( 'the number of sides of the polygon cannot be less than 3,' ) coefficient = fdiv( k, 2 ) return polyval( [ coefficient, fneg( coefficient ), 1 ], real( n ) )
def getNthCenteredPolygonalNumber(n, k): coefficient = fdiv(k, 2) return polyval([coefficient, fneg(coefficient), 1], n)
def getFactors( n ): ''' A factorization of *Nptr into prime and q-prime factors is first obtained. Selfridge's primality test is then applied to any q-prime factors; the test is applied repeatedly until either a q-prime is found to be composite or likely to be composite (in which case the initial factorization is doubtful and an extra base should be used in Miller's test) or we run out of q-primes, in which case every q-prime factor of *Nptr is certified as prime. Returns a list of tuples where each tuple is a prime factor and an exponent. ''' verbose = g.verbose if real( n ) < -1: return [ ( -1, 1 ) ] + getFactors( fneg( n ) ) elif n == -1: return [ ( -1, 1 ) ] elif n == 0: return [ ( 0, 1 ) ] elif n == 1: return [ ( 1, 1 ) ] target = int( n ) dps = ceil( log( n ) ) if dps > mp.dps: setAccuracy( dps ) if target > g.minValueToCache: if g.factorCache is None: loadFactorCache( ) if target in g.factorCache: if verbose: print( 'cache hit:', target ) return g.factorCache[ target ] smallFactors, largeFactors, qPrimes = getPrimeFactors( int( n ), verbose ) if qPrimes: if verbose: print( 'testing q-primes for primality' ) print( '--' ) i = 0 for qPrime in qPrimes: t = doSelfridgeTest( qPrime[ 0 ], verbose ) if not t: print( 'do FACTOR() again with an extra base' ) return 0 if verbose: print( 'all q-primes are primes:', n, 'has the following factorization:' ) print( ) for i in smallFactors: print( 'prime factor:', i[ 0 ], 'exponent:', i[ 1 ] ) for i in largeFactors: print( 'prime factor:', i[ 0 ], 'exponent:', i[ 1 ] ) else: if verbose: print( 'NO Q-PRIMES:' ) print( ) print( n, 'has the following factorization:' ) for i in smallFactors: print( 'prime factor:', i[ 0 ], 'exponent:', i[ 1 ] ) for i in largeFactors: print( 'prime factor:', i[ 0 ], 'exponent:', i[ 1 ] ) result = [ ] result.extend( smallFactors ) result.extend( largeFactors ) if g.factorCache is not None: product = int( fprod( [ power( i[ 0 ], i[ 1 ] ) for i in largeFactors ] ) ) if product not in g.factorCache: g.factorCache[ product ] = largeFactors g.factorCacheIsDirty = True if n > g.minValueToCache and n not in g.factorCache: g.factorCache[ n ] = result g.factorCacheIsDirty = True return result
def getNthPolygonalNumber(n, k): coeff = fdiv(fsub(k, 2), 2) # validateRealInt isn't happy, why? return polyval([coeff, fneg(fsub(coeff, 1)), 0], int(n))
def solveQuarticPolynomial( _a, _b, _c, _d, _e ): if mp.dps < 50: mp.dps = 50 # maybe it's really an order-3 polynomial if _a == 0: return solveCubicPolynomial( _b, _c, _d, _e ) # degenerate case, just return the two real and two imaginary 4th roots of the # constant term divided by the 4th root of a elif _b == 0 and _c == 0 and _d == 0: e = fdiv( _e, _a ) f = root( _a, 4 ) x1 = fdiv( root( fneg( e ), 4 ), f ) x2 = fdiv( fneg( root( fneg( e ), 4 ) ), f ) x3 = fdiv( mpc( 0, root( fneg( e ), 4 ) ), f ) x4 = fdiv( mpc( 0, fneg( root( fneg( e ), 4 ) ) ), f ) return [ x1, x2, x3, x4 ] # otherwise we have a regular quartic to solve b = fdiv( _b, _a ) c = fdiv( _c, _a ) d = fdiv( _d, _a ) e = fdiv( _e, _a ) # we turn the equation into a cubic that we can solve f = fsub( c, fdiv( fmul( 3, power( b, 2 ) ), 8 ) ) g = fsum( [ d, fdiv( power( b, 3 ), 8 ), fneg( fdiv( fmul( b, c ), 2 ) ) ] ) h = fsum( [ e, fneg( fdiv( fmul( 3, power( b, 4 ) ), 256 ) ), fmul( power( b, 2 ), fdiv( c, 16 ) ), fneg( fdiv( fmul( b, d ), 4 ) ) ] ) y1, y2, y3 = solveCubicPolynomial( 1, fdiv( f, 2 ), fdiv( fsub( power( f, 2 ), fmul( 4, h ) ), 16 ), fneg( fdiv( power( g, 2 ), 64 ) ) ) # pick two non-zero roots, if there are two imaginary roots, use them if y1 == 0: root1 = y2 root2 = y3 elif y2 == 0: root1 = y1 root2 = y3 elif y3 == 0: root1 = y1 root2 = y2 elif im( y1 ) != 0: root1 = y1 if im( y2 ) != 0: root2 = y2 else: root2 = y3 else: root1 = y2 root2 = y3 # more variables... p = sqrt( root1 ) q = sqrt( root2 ) r = fdiv( fneg( g ), fprod( [ 8, p, q ] ) ) s = fneg( fdiv( b, 4 ) ) # put together the 4 roots x1 = fsum( [ p, q, r, s ] ) x2 = fsum( [ p, fneg( q ), fneg( r ), s ] ) x3 = fsum( [ fneg( p ), q, fneg( r ), s ] ) x4 = fsum( [ fneg( p ), fneg( q ), r, s ] ) return [ chop( x1 ), chop( x2 ), chop( x3 ), chop( x4 ) ]
def _hasNegative(self, vec): for i in range(len(vec)): if vec[i] <= mp.fneg(self.tolerance): return True return False
def alternateSigns( n, startNegative = False ): negative = startNegative for i in n: yield fneg( i ) if negative else i negative = not negative
def solveCubicPolynomial( a, b, c, d ): # pylint: disable=invalid-name ''' This function applies the cubic formula to solve a polynomial with coefficients of a, b, c and d. ''' if mp.dps < 50: mp.dps = 50 if a == 0: return solveQuadraticPolynomial( b, c, d ) f = fdiv( fsub( fdiv( fmul( 3, c ), a ), fdiv( power( b, 2 ), power( a, 2 ) ) ), 3 ) g = fdiv( fadd( fsub( fdiv( fmul( 2, power( b, 3 ) ), power( a, 3 ) ), fdiv( fprod( [ 9, b, c ] ), power( a, 2 ) ) ), fdiv( fmul( 27, d ), a ) ), 27 ) h = fadd( fdiv( power( g, 2 ), 4 ), fdiv( power( f, 3 ), 27 ) ) # all three roots are the same if h == 0: x1 = fneg( root( fdiv( d, a ), 3 ) ) x2 = x1 x3 = x2 # two imaginary and one real root elif h > 0: r = fadd( fneg( fdiv( g, 2 ) ), sqrt( h ) ) if r < 0: s = fneg( root( fneg( r ), 3 ) ) else: s = root( r, 3 ) t = fsub( fneg( fdiv( g, 2 ) ), sqrt( h ) ) if t < 0: u = fneg( root( fneg( t ), 3 ) ) else: u = root( t, 3 ) x1 = fsub( fadd( s, u ), fdiv( b, fmul( 3, a ) ) ) real = fsub( fdiv( fneg( fadd( s, u ) ), 2 ), fdiv( b, fmul( 3, a ) ) ) imaginary = fdiv( fmul( fsub( s, u ), sqrt( 3 ) ), 2 ) x2 = mpc( real, imaginary ) x3 = mpc( real, fneg( imaginary ) ) # all real roots else: j = sqrt( fsub( fdiv( power( g, 2 ), 4 ), h ) ) k = acos( fneg( fdiv( g, fmul( 2, j ) ) ) ) if j < 0: l = fneg( root( fneg( j ), 3 ) ) else: l = root( j, 3 ) m = cos( fdiv( k, 3 ) ) n = fmul( sqrt( 3 ), sin( fdiv( k, 3 ) ) ) p = fneg( fdiv( b, fmul( 3, a ) ) ) x1 = fsub( fmul( fmul( 2, l ), cos( fdiv( k, 3 ) ) ), fdiv( b, fmul( 3, a ) ) ) x2 = fadd( fmul( fneg( l ), fadd( m, n ) ), p ) x3 = fadd( fmul( fneg( l ), fsub( m, n ) ), p ) return [ chop( x1 ), chop( x2 ), chop( x3 ) ]
def solveQuarticPolynomialOperator( _a, _b, _c, _d, _e ): # pylint: disable=invalid-name ''' This function applies the quartic formula to solve a polynomial with coefficients of a, b, c, d, and e. ''' if mp.dps < 50: mp.dps = 50 # maybe it's really an order-3 polynomial if _a == 0: return solveCubicPolynomial( _b, _c, _d, _e ) # degenerate case, just return the two real and two imaginary 4th roots of the # constant term divided by the 4th root of a if _b == 0 and _c == 0 and _d == 0: e = fdiv( _e, _a ) f = root( _a, 4 ) x1 = fdiv( root( fneg( e ), 4 ), f ) x2 = fdiv( fneg( root( fneg( e ), 4 ) ), f ) x3 = fdiv( mpc( 0, root( fneg( e ), 4 ) ), f ) x4 = fdiv( mpc( 0, fneg( root( fneg( e ), 4 ) ) ), f ) return [ x1, x2, x3, x4 ] # otherwise we have a regular quartic to solve b = fdiv( _b, _a ) c = fdiv( _c, _a ) d = fdiv( _d, _a ) e = fdiv( _e, _a ) # we turn the equation into a cubic that we can solve f = fsub( c, fdiv( fmul( 3, power( b, 2 ) ), 8 ) ) g = fsum( [ d, fdiv( power( b, 3 ), 8 ), fneg( fdiv( fmul( b, c ), 2 ) ) ] ) h = fsum( [ e, fneg( fdiv( fmul( 3, power( b, 4 ) ), 256 ) ), fmul( power( b, 2 ), fdiv( c, 16 ) ), fneg( fdiv( fmul( b, d ), 4 ) ) ] ) roots = solveCubicPolynomial( 1, fdiv( f, 2 ), fdiv( fsub( power( f, 2 ), fmul( 4, h ) ), 16 ), fneg( fdiv( power( g, 2 ), 64 ) ) ) y1 = roots[ 0 ] y2 = roots[ 1 ] y3 = roots[ 2 ] # pick two non-zero roots, if there are two imaginary roots, use them if y1 == 0: root1 = y2 root2 = y3 elif y2 == 0: root1 = y1 root2 = y3 elif y3 == 0: root1 = y1 root2 = y2 elif im( y1 ) != 0: root1 = y1 if im( y2 ) != 0: root2 = y2 else: root2 = y3 else: root1 = y2 root2 = y3 # more variables... p = sqrt( root1 ) q = sqrt( root2 ) r = fdiv( fneg( g ), fprod( [ 8, p, q ] ) ) s = fneg( fdiv( b, 4 ) ) # put together the 4 roots x1 = fsum( [ p, q, r, s ] ) x2 = fsum( [ p, fneg( q ), fneg( r ), s ] ) x3 = fsum( [ fneg( p ), q, fneg( r ), s ] ) x4 = fsum( [ fneg( p ), fneg( q ), r, s ] ) return [ chop( x1 ), chop( x2 ), chop( x3 ), chop( x4 ) ]
def getNthBaseKRepunit( n, k ): return getNthLinearRecurrence( [ fneg( real( k ) ), fadd( k, 1 ) ], [ 1, fadd( k, 1 ) ], n )
def getNegative( n ): if isinstance( n, RPNMeasurement ): return RPNMeasurement( fneg( n.value ), n.units ) else: return fneg( n )
def getNegativeOperator(n): if isinstance(n, RPNMeasurement): return RPNMeasurement(fneg(n.value), n.units) return fneg(n)
def parseInputValue( term, inputRadix ): if isinstance( term, mpf ): return term innerChars = term[ 1 : -1 ] # this helps us parse dates if '/' in innerChars: term = term.replace( '/', '-' ) innerChars = term[ 1 : -1 ] # 'e' implies scientific notation, which isn't a date regardless if ( 'e' not in innerChars ): # 'd' means a dice expression, '[' means a build_number expression, so don't treat it as a date if ( ( '-' in innerChars ) or ( ':' in innerChars ) ) and ( 'd' not in term ) and ( '[' not in term ): # try: datetime = arrow.get( term ) datetime = RPNDateTime( datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, datetime.microsecond ) # except: # raise ValueError( 'error parsing datetime' ) return datetime if term == '0': return mpmathify( 0 ) # ignore commas term = ''.join( [ i for i in term if i not in ',' ] ) if term[ 0 ] == '\\': term = term[ 1 : ] ignoreSpecial = True else: ignoreSpecial = False if '.' in term: if inputRadix == 10: newPrecision = len( term ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) return mpmathify( term ) decimal = term.find( '.' ) else: decimal = len( term ) negative = term[ 0 ] == '-' if negative: start = 1 else: if term[ 0 ] == '+': start = 1 else: start = 0 integer = term[ start : decimal ] mantissa = term[ decimal + 1 : ] # check for hex, then binary, then octal, otherwise a plain old decimal integer if not ignoreSpecial and mantissa == '': if integer[ 0 ] == '0': if len( integer ) == 1: return mpmathify( 0 ) if integer[ 1 ] in 'Xx': # set the precision big enough to handle this value newPrecision = math.ceil( ( math.log10( 16 ) * ( len( integer ) - 2 ) ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) return mpmathify( int( integer[ 2 : ], 16 ) ) elif integer[ -1 ] in 'bB': # set the precision big enough to handle this value newPrecision = math.ceil( math.log10( 2 ) * ( len( integer ) - 1 ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) integer = integer[ : -1 ] return mpmathify( int( integer, 2 ) * ( -1 if negative else 1 ) ) else: integer = integer[ 1 : ] return mpmathify( int( integer, 8 ) ) if integer[ 0 ] == '1' and integer[ -1 ] in 'bB': # set the precision big enough to handle this value newPrecision = math.ceil( math.log10( 2 ) * ( len( integer ) - 1 ) ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) integer = integer[ : -1 ] return mpmathify( int( integer, 2 ) * ( -1 if negative else 1 ) ) elif inputRadix == 10: newPrecision = len( integer ) + 1 if mp.dps < newPrecision: setAccuracy( newPrecision ) return fneg( integer ) if negative else mpmathify( integer ) # finally, we have a non-radix 10 number to parse result = convertToBase10( integer, mantissa, inputRadix ) return fneg( result ) if negative else mpmathify( result )