import Complex , { Cx } from './Complex' ; import Vector from './Vector' ; import Operator from './Operator' ; import Dimension from './Dimension' ; import { TAU } from './Constants' ; const dimPol = Dimension . polarization ( ) ; const dimDir = Dimension . direction ( ) ; const idPol = Operator . identity ( [ dimPol ] ) ; const idDir = Operator . identity ( [ dimDir ] ) ; const cos = ( alpha ) : Complex => Cx ( Math . cos ( alpha ) , 0 ) ; const sin = ( alpha ) : Complex => Cx ( Math . sin ( alpha ) , 0 ) ; const mod = ( x , n ) : number => ( ( x % n ) + n ) % n ; export const isqrt2 = Cx ( Math . SQRT1_2 ) ; const toPolVec = ( array ) : Vector => Vector . fromArray ( array , [ dimPol ] ) . normalize ( ) ; /**
 * Vectors for polarization states: H, V, D, A, L, R.
 */ export const polStates = { H : toPolVec ( [ Cx ( 1 ) , Cx ( 0 ) ] ) , V : toPolVec ( [ Cx ( 0 ) , Cx ( 1 ) ] ) , D : toPolVec ( [ Cx ( 1 ) , Cx ( 1 ) ] ) , A : toPolVec ( [ Cx ( - 1 ) , Cx ( 1 ) ] ) , L : toPolVec ( [ Cx ( 1 ) , Cx ( 0 , 1 ) ] ) , R : toPolVec ( [ Cx ( 1 ) , Cx ( 0 , - 1 ) ] ) , } ; param alpha param dimension export function rotationMatrix ( alpha , dimension ) { const array = [ [ cos ( alpha ) , sin ( - alpha ) ] , [ sin ( alpha ) , cos ( alpha ) ] , ] ; return Operator . fromArray ( array , [ dimension ] ) ; } param alpha param dimension export function projectionMatrix ( alpha , dimension ) { const array = [ [ cos ( alpha ) . mul ( cos ( alpha ) ) , cos ( alpha ) . mul ( sin ( alpha ) ) ] , [ cos ( alpha ) . mul ( sin ( alpha ) ) , sin ( alpha ) . mul ( sin ( alpha ) ) ] , ] ; return Operator . fromArray ( array , [ dimension ] ) ; } param alpha param phase param phaseOrthogonal param dimension export function phaseShiftForRealEigenvectors ( alpha , phase , phaseOrthogonal , dimension ) { return Operator . add ( [ projectionMatrix ( alpha , dimension ) . mulConstant ( Complex . fromPolar ( 1 , phase * TAU ) ) , projectionMatrix ( alpha + 0.25 * TAU , dimension ) . mulConstant ( Complex . fromPolar ( 1 , phaseOrthogonal * TAU ) ) , ] ) ; } /**
 * Reflection from an optically lighter material.
 * Note that change horizontal frame of reference.
 */ export function reflectPhaseFromLighter ( ) { const array = [ [ Cx ( - 1 ) , Cx ( 0 ) ] , [ Cx ( 0 ) , Cx ( 1 ) ] , ] ; return Operator . fromArray ( array , [ dimPol ] , [ dimPol ] ) ; } /**
 * Reflection from an optically denser material.
 * Note that change horizontal frame of reference.
 */ export function reflectPhaseFromDenser ( ) { const array = [ [ Cx ( 1 ) , Cx ( 0 ) ] , [ Cx ( 0 ) , Cx ( - 1 ) ] , ] ; return Operator . fromArray ( array , [ dimPol ] , [ dimPol ] ) ; } param r param rot export function amplitudeIntensity ( r , rot ) { return Operator . outer ( [ idDir , idPol ] ) . mulConstant ( Complex . fromPolar ( r , TAU * rot ) ) ; } param angle returns export function reflectFromPlaneDirection ( angle ) { let sparseCoords ; switch ( mod ( angle , 180 ) ) { case 0 : sparseCoords = [ [ 'v' , '^' , Cx ( 1 ) ] , [ '^' , 'v' , Cx ( 1 ) ] , ] ; break ; case 45 : sparseCoords = [ [ '^' , '>' , Cx ( 1 ) ] , [ '>' , '^' , Cx ( 1 ) ] , [ 'v' , '<' , Cx ( 1 ) ] , [ '<' , 'v' , Cx ( 1 ) ] , ] ; break ; case 90 : sparseCoords = [ [ '<' , '>' , Cx ( 1 ) ] , [ '>' , '<' , Cx ( 1 ) ] , ] ; break ; case 135 : sparseCoords = [ [ 'v' , '>' , Cx ( 1 ) ] , [ '>' , 'v' , Cx ( 1 ) ] , [ '^' , '<' , Cx ( 1 ) ] , [ '<' , '^' , Cx ( 1 ) ] , ] ; break ; default : throw new Error ( `Angle ${ angle } % 180 isn't in the set [0, 45, 90, 135]` ) ; } return Operator . fromSparseCoordNames ( sparseCoords , [ dimDir ] ) ; } param angle returns export function beamsplitterTransmittionDirections ( angle ) { switch ( mod ( angle , 180 ) ) { case 0 : return Operator . fromSparseCoordNames ( [ [ '^' , '^' , Cx ( 1 ) ] , [ 'v' , 'v' , Cx ( 1 ) ] , ] , [ dimDir ] ) ; case 45 : case 135 : return idDir ; case 90 : return Operator . fromSparseCoordNames ( [ [ '>' , '>' , Cx ( 1 ) ] , [ '<' , '<' , Cx ( 1 ) ] , ] , [ dimDir ] ) ; default : throw new Error ( `Angle ${ angle } % 180 isn't in the set [0, 45, 90, 135].` ) ; } } const diodeRight = Operator . fromSparseCoordNames ( [ [ '>' , '>' , Cx ( 1 ) ] ] , [ dimDir ] ) ; const diodeUp = Operator . fromSparseCoordNames ( [ [ '^' , '^' , Cx ( 1 ) ] ] , [ dimDir ] ) ; const diodeLeft = Operator . fromSparseCoordNames ( [ [ '<' , '<' , Cx ( 1 ) ] ] , [ dimDir ] ) ; const diodeDown = Operator . fromSparseCoordNames ( [ [ 'v' , 'v' , Cx ( 1 ) ] ] , [ dimDir ] ) ; param angle returns export function diodeForDirections ( angle ) { switch ( mod ( angle , 360 ) ) { case 0 : return diodeRight ; case 90 : return diodeUp ; case 180 : return diodeLeft ; case 270 : return diodeDown ; default : throw new Error ( `Angle ${ angle } % 360 isn't in the set [0, 90, 180, 270].` ) ; } }