"""Original bounded exact barycentric evaluation with exact-node branch."""
from fractions import Fraction as F
from math import prod
import json

def validate(xs,ys,x):
 if type(xs) is not list or type(ys) is not list or not 1<=len(xs)<=8 or len(xs)!=len(ys) or any(type(v) not in [int,F] or abs(v)>100 for v in xs+ys+[x]) or len(set(xs))!=len(xs):raise ValueError('1..8 distinct exact nodes, matching bounded values and query')

def bary(xs,ys,x):
 validate(xs,ys,x);xs=list(map(F,xs));ys=list(map(F,ys));x=F(x);weights=[1/prod((xi-xj for j,xj in enumerate(xs) if i!=j),start=F(1)) for i,xi in enumerate(xs)]
 if x in xs:return ys[xs.index(x)],weights,[], 'exact_node_return'
 rows=[];num=F(0);den=F(0)
 for xi,yi,wi in zip(xs,ys,weights):
  term=wi/(x-xi);num+=term*yi;den+=term;rows.append({'node':str(xi),'weight_over_distance':str(term),'numerator_contribution':str(term*yi)})
 if den==0:raise ValueError('unexpected zero barycentric denominator')
 return num/den,weights,rows,'barycentric_ratio'

def lagrange(xs,ys,x):
 total=F(0)
 for i in range(len(xs)):
  term=F(ys[i])
  for j in range(len(xs)):
   if i!=j:term*=F(x-xs[j],xs[i]-xs[j])
  total+=term
 return total

def demo():
 xs=[F(0),F(1),F(2)];ys=[F(1),F(2),F(5)];queries=[F(i,4) for i in range(-4,13)];rows=[]
 for x in queries:
  value,weights,tr,kind=bary(xs,ys,x);assert value==lagrange(xs,ys,x)==1+x*x;rows.append({'query':str(x),'value':str(value),'status':kind,'terms':tr})
 assert bary(xs,ys,F(1,2))[0]==F(5,4)
 rx=[F(-1),F(-1,2),F(0),F(1,2),F(1)];ry=[1/(1+25*x*x) for x in rx];rq=F(3,4);pv,ww,tr,kind=bary(rx,ry,rq);true=1/(1+25*rq*rq);assert pv==lagrange(rx,ry,rq) and pv<0<true
 runge_node_checks=[]
 for x,y in zip(rx,ry):
  val,_,_,s=bary(rx,ry,x);assert val==y and s=='exact_node_return';runge_node_checks.append({'x':str(x),'exact_y_returned':str(val)})
 permutations_checked=0
 from itertools import permutations
 for order in permutations(range(3)):
  xx=[xs[i] for i in order];yy=[ys[i] for i in order];assert bary(xx,yy,F(1,2))[0]==F(5,4);permutations_checked+=1
 rejected=[]
 for label,xs0,ys0 in [('duplicate_same_y',[0,0],[1,1]),('duplicate_different_y',[0,0],[1,2]),('mismatch',[0,1],[1]),('empty',[],[]),('nonfinite',[0,float('nan')],[1,2]),('bool',[0,True],[1,2]),('too_many',list(range(9)),list(range(9)))]:
  try:bary(xs0,ys0,F(1,2))
  except ValueError:rejected.append(label)
  else:raise AssertionError('expected rejection')
 return {'quadratic_nodes':[str(x) for x in xs],'quadratic_values':[str(x) for x in ys],'barycentric_weights':[str(x) for x in weights],'seventeen_quarter_grid_queries_with_Lagrange_oracle':rows,'all_six_node_permutations_checked':permutations_checked,'interior_Runge_counterexample':{'function':'1/(1+25*x*x)','nodes':[str(x) for x in rx],'values':[str(x) for x in ry],'query':str(rq),'polynomial_interpolant':str(pv),'true_function':str(true),'all_five_nodes_match':runge_node_checks,'terms':tr},'invalid_inputs_rejected':rejected,'scope':'exact finite interpolation, not regression/SMOTE/statistical confidence or SciPy execution; barycentric representation does not remove intrinsic polynomial interpolation error/Runge phenomenon; node equality branch avoids division by0'}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=True,indent=2))
