From: Samuel Lepetit Date: Fri, 18 May 2012 13:03:32 +0000 (+0200) Subject: Add chord example for java X-Git-Tag: v3_9_90~569^2~19^2~70^2 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/dc0a22c53a395e19ce8e65b64cb2a51c36aea261 Add chord example for java --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f097deb049..660e1aa8d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,14 @@ set(JMSG_JAVA_SRC ) set(JAVA_EXAMPLES - + examples/chord/Chord.java + examples/chord/Common.java + examples/chord/Node.java + examples/chord/ChordTask.java + examples/chord/FindSuccessorAnswerTask.java + examples/chord/FindSuccessorTask.java + examples/chord/GetPredecessorAnswerTask.java + examples/chord/NotifyTask.java examples/mutualExclusion/centralized/MutexCentral.java examples/mutualExclusion/centralized/GrantTask.java examples/mutualExclusion/centralized/Coordinator.java @@ -238,11 +245,12 @@ add_custom_command( DEPENDS ${JAVA_EXAMPLES} COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/basic/*.java COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/async/*.java - COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/pingPong/*.java + COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/chord/*.java COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/commTime/*.java + COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/master_slave_bypass/*.java + COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/master_slave_kill/*.java COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/mutualExclusion/centralized/*.java - COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/master_slave_bypass/*.java - COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/master_slave_kill/*.java + COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/pingPong/*.java COMMAND ${JAVA_COMPILE} -d ${CMAKE_HOME_DIRECTORY}/examples -cp ${CMAKE_HOME_DIRECTORY}/simgrid.jar ${CMAKE_HOME_DIRECTORY}/examples/startKillTime/*.java ) diff --git a/examples/chord/Chord.java b/examples/chord/Chord.java new file mode 100644 index 0000000000..66f8e1b7c5 --- /dev/null +++ b/examples/chord/Chord.java @@ -0,0 +1,21 @@ +package chord; + +import org.simgrid.msg.Msg; + +public class Chord { + public static void main(String[] args) { + /* initialize the MSG simulation. Must be done before anything else (even logging). */ + Msg.init(args); + if(args.length < 2) { + Msg.info("Usage : Chord platform_file deployment_file"); + Msg.info("example : Chord platform.xml deployment.xml"); + System.exit(1); + } + /* construct the platform and deploy the application */ + Msg.createEnvironment(args[0]); + Msg.deployApplication(args[1]); + + /* execute the simulation. */ + Msg.run(); + } +} diff --git a/examples/chord/ChordTask.java b/examples/chord/ChordTask.java new file mode 100644 index 0000000000..b740feaa07 --- /dev/null +++ b/examples/chord/ChordTask.java @@ -0,0 +1,20 @@ +package chord; + +import org.simgrid.msg.Task; + +import chord.Common; +/** + * Base class for all Tasks in Chord. + */ +public class ChordTask extends Task { + public String issuerHostName; + public String answerTo; + public ChordTask() { + this(null,null); + } + public ChordTask(String issuerHostName, String answerTo) { + super(null, Common.COMP_SIZE, Common.COMM_SIZE); + this.issuerHostName = issuerHostName; + this.answerTo = answerTo; + } +} diff --git a/examples/chord/Common.java b/examples/chord/Common.java new file mode 100644 index 0000000000..d12f10b476 --- /dev/null +++ b/examples/chord/Common.java @@ -0,0 +1,17 @@ +package chord; +/** + * Common constants used over the simulation + */ +public class Common { + public final static int COMM_SIZE = 10; + public final static int COMP_SIZE = 0; + + public final static int NB_BITS = 24; + public final static int NB_KEYS = 16777216; + public final static int TIMEOUT = 50; + public final static int MAX_SIMULATION_TIME = 1000; + public final static int PERIODIC_STABILIZE_DELAY = 20; + public final static int PERIODIC_FIX_FINGERS_DELAY = 120; + public final static int PERIODIC_CHECK_PREDECESSOR_DELAY = 120; + public final static int PERIODIC_LOOKUP_DELAY = 10; +} diff --git a/examples/chord/FindSuccessorAnswerTask.java b/examples/chord/FindSuccessorAnswerTask.java new file mode 100644 index 0000000000..dea6ce1f3e --- /dev/null +++ b/examples/chord/FindSuccessorAnswerTask.java @@ -0,0 +1,10 @@ +package chord; + +public class FindSuccessorAnswerTask extends ChordTask { + public int answerId; + + public FindSuccessorAnswerTask(String issuerHostname, String answerTo, int answerId) { + super(issuerHostname,answerTo); + this.answerId = answerId; + } +} diff --git a/examples/chord/FindSuccessorTask.java b/examples/chord/FindSuccessorTask.java new file mode 100644 index 0000000000..2b068f0550 --- /dev/null +++ b/examples/chord/FindSuccessorTask.java @@ -0,0 +1,10 @@ +package chord; + +public class FindSuccessorTask extends ChordTask { + public int requestId; + + public FindSuccessorTask(String issuerHostname, String answerTo, int requestId) { + super(issuerHostname, answerTo); + this.requestId = requestId; + } +} diff --git a/examples/chord/GetPredecessorAnswerTask.java b/examples/chord/GetPredecessorAnswerTask.java new file mode 100644 index 0000000000..493bffaeb5 --- /dev/null +++ b/examples/chord/GetPredecessorAnswerTask.java @@ -0,0 +1,9 @@ +package chord; + +public class GetPredecessorAnswerTask extends ChordTask { + public int answerId; + public GetPredecessorAnswerTask(String issuerHostname, String answerTo, int answerId) { + super(issuerHostname,answerTo); + this.answerId = answerId; + } +} diff --git a/examples/chord/GetPredecessorTask.java b/examples/chord/GetPredecessorTask.java new file mode 100644 index 0000000000..42dd2e9b3b --- /dev/null +++ b/examples/chord/GetPredecessorTask.java @@ -0,0 +1,7 @@ +package chord; + +public class GetPredecessorTask extends ChordTask { + public GetPredecessorTask(String issuerHostName, String answerTo) { + super(issuerHostName, answerTo); + } +} diff --git a/examples/chord/Node.java b/examples/chord/Node.java new file mode 100644 index 0000000000..2727dd998d --- /dev/null +++ b/examples/chord/Node.java @@ -0,0 +1,471 @@ +package chord; + +import org.simgrid.msg.Comm; +import org.simgrid.msg.Host; +import org.simgrid.msg.Msg; +import org.simgrid.msg.MsgException; +import org.simgrid.msg.Process; +import org.simgrid.msg.Task; +import org.simgrid.msg.TimeoutException; +/** + * Node data + */ +public class Node extends Process { + /** + * Node id + */ + protected int id; + /** + * Node mailbox + */ + protected String mailbox; + /** + * Predecessor id + */ + protected int predId; + /** + * Predecessor mailbox + */ + protected String predMailbox; + /** + * Index of the next finger to fix + */ + protected int nextFingerToFix; + /** + * Current communication + */ + protected Comm commReceive; + /** + * Last time I changed a finger or my predecessor + */ + protected double lastChangeDate; + /** + * Node fingers + */ + int fingers[]; + /** + * Constructor + */ + public Node(Host host, String name, String[] args) { + super(host,name,args); + } + @Override + public void main(String[] args) throws MsgException { + if (args.length != 2 && args.length != 4) { + Msg.info("You need to provide 2 or 4 arguments."); + return; + } + double initTime = Msg.getClock(); + int i; + boolean joinSuccess = false; + double deadline; + + double nextStabilizeDate = initTime + Common.PERIODIC_STABILIZE_DELAY; + double nextFixFingersDate = initTime + Common.PERIODIC_FIX_FINGERS_DELAY; + double nextCheckPredecessorDate = initTime + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; + double nextLookupDate = initTime + Common.PERIODIC_LOOKUP_DELAY; + + id = Integer.valueOf(args[0]); + mailbox = Integer.toString(id); + + fingers = new int[Common.NB_BITS]; + for (i = 0; i < Common.NB_BITS; i++) { + fingers[i] = -1; + setFinger(i,this.id); + } + + //First node + if (args.length == 2) { + deadline = Integer.valueOf(args[1]); + create(); + joinSuccess = true; + } + else { + int knownId = Integer.valueOf(args[1]); + deadline = Integer.valueOf(args[3]); + //Msg.info("Hey! Let's join the system with the id " + id + "."); + + joinSuccess = join(knownId); + } + if (joinSuccess) { + double currentClock = Msg.getClock(); + while (currentClock < (initTime + deadline) && currentClock < Common.MAX_SIMULATION_TIME) { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + try { + if (!commReceive.test()) { + if (currentClock >= nextStabilizeDate) { + stabilize(); + nextStabilizeDate = Msg.getClock() + Common.PERIODIC_STABILIZE_DELAY; + } + else if (currentClock >= nextFixFingersDate) { + fixFingers(); + nextFixFingersDate = Msg.getClock() + Common.PERIODIC_FIX_FINGERS_DELAY; + } + else if (currentClock >= nextCheckPredecessorDate) { + this.checkPredecessor(); + nextCheckPredecessorDate = Msg.getClock() + Common.PERIODIC_CHECK_PREDECESSOR_DELAY; + } + else if (currentClock >= nextLookupDate) { + this.randomLookup(); + nextLookupDate = Msg.getClock() + Common.PERIODIC_LOOKUP_DELAY; + } + else { + waitFor(5); + } + currentClock = Msg.getClock(); + } + else { + handleTask(commReceive.getTask()); + currentClock = Msg.getClock(); + commReceive = null; + + } + } + catch (Exception e) { + + } + + } + leave(); + if (commReceive != null) { + commReceive = null; + } + } + else { + Msg.info("I couldn't join the ring"); + } + } + void handleTask(Task task) { + if (task instanceof FindSuccessorTask) { + FindSuccessorTask fTask = (FindSuccessorTask)task; + Msg.debug("Receiving a 'Find Successor' request from " + fTask.issuerHostName + " for id " + fTask.requestId); + // is my successor the successor? + if (isInInterval(fTask.requestId, this.id + 1, fingers[0])) { + //Msg.info("Send the request to " + fTask.answerTo + " with answer " + fingers[0]); + FindSuccessorAnswerTask answer = new FindSuccessorAnswerTask(host.getName(), mailbox, fingers[0]); + answer.dsend(fTask.answerTo); + } + else { + // otherwise, forward the request to the closest preceding finger in my table + int closest = closestPrecedingNode(fTask.requestId); + //Msg.info("Forward the request to " + closest); + fTask.dsend(Integer.toString(closest)); + } + } + else if (task instanceof GetPredecessorTask) { + GetPredecessorTask gTask = (GetPredecessorTask)(task); + Msg.debug("Receiving a 'Get Predecessor' request from " + gTask.issuerHostName); + GetPredecessorAnswerTask answer = new GetPredecessorAnswerTask(host.getName(), mailbox, predId); + answer.dsend(gTask.answerTo); + } + else if (task instanceof NotifyTask) { + NotifyTask nTask = (NotifyTask)task; + notify(nTask.requestId); + } + else { + Msg.debug("Ignoring unexpected task of type:" + task); + } + } + /** + * @brief Makes the current node quit the system + */ + void leave() { + Msg.debug("Well Guys! I Think it's time for me to quit ;)"); + quitNotify(1); //Notify my successor + quitNotify(-1); //Notify my predecessor. + // TODO ... + } + /** + * @brief Notifies the successor or the predecessor of the current node + * of the departure + * @param to 1 to notify the successor, -1 to notify the predecessor + */ + static void quitNotify( int to) { + //TODO + } + /** + * @brief Initializes the current node as the first one of the system. + */ + void create() { + Msg.debug("Create a new Chord ring..."); + setPredecessor(-1); + + } + /** + * Makes the current node join the ring, knowing the id of a node + * already in the ring + */ + boolean join(int knownId) { + Msg.info("Joining the ring with id " + this.id + " knowing node " + knownId); + setPredecessor(-1); + int successorId = remoteFindSuccessor(knownId, this.id); + if (successorId == -1) { + Msg.info("Cannot join the ring."); + } + else { + setFinger(0, successorId); + } + return successorId != -1; + } + + /** + * Sets the node predecessor + */ + void setPredecessor(int predecessorId) { + if (predecessorId != predId) { + predId = predecessorId; + if (predecessorId != -1) { + predMailbox = Integer.toString(predId); + } + lastChangeDate = Msg.getClock(); + } + } + /** + * @brief Asks another node its predecessor. + * @param askTo the node to ask to + * @return the id of its predecessor node, or -1 if the request failed + * (or if the node does not know its predecessor) + */ + int remoteGetPredecessor(int askTo) { + int predecessorId = -1; + boolean stop = false; + Msg.debug("Sending a 'Get Predecessor' request to " + askTo); + String mailboxTo = Integer.toString(askTo); + GetPredecessorTask sendTask = new GetPredecessorTask(host.getName(), this.mailbox); + try { + sendTask.send(mailboxTo, Common.TIMEOUT); + try { + do { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + commReceive.waitCompletion(Common.TIMEOUT); + Task taskReceived = commReceive.getTask(); + if (taskReceived instanceof GetPredecessorAnswerTask) { + predecessorId = ((GetPredecessorAnswerTask) taskReceived).answerId; + stop = true; + } + else { + handleTask(taskReceived); + } + commReceive = null; + } while (!stop); + + } + catch (MsgException e) { + commReceive = null; + stop = true; + } + } + catch (MsgException e) { + Msg.debug("Failed to send the Get Predecessor request"); + } + + + return predecessorId; + } + /** + * @brief Makes the current node find the successor node of an id. + * @param node the current node + * @param id the id to find + * @return the id of the successor node, or -1 if the request failed + */ + int findSuccessor(int id) { + if (isInInterval(id, this.id + 1, fingers[0])) { + return fingers[0]; + } + + int closest = this.closestPrecedingNode(id); + return remoteFindSuccessor(closest, id); + } + /** + * @brief Asks another node the successor node of an id. + */ + int remoteFindSuccessor(int askTo, int id) { + int successor = -1; + boolean stop = false; + String mailbox = Integer.toString(askTo); + Task sendTask = new FindSuccessorTask(host.getName(), this.mailbox, id); + Msg.debug("Sending a 'Find Successor' request to " + mailbox + " for id " + id); + try { + sendTask.send(mailbox, Common.TIMEOUT); + do { + if (commReceive == null) { + commReceive = Task.irecv(this.mailbox); + } + try { + commReceive.waitCompletion(Common.TIMEOUT); + Task task = commReceive.getTask(); + if (task instanceof FindSuccessorAnswerTask) { + //TODO: Check if this this our answer. + FindSuccessorAnswerTask fTask = (FindSuccessorAnswerTask) task; + stop = true; + successor = fTask.answerId; + } + else { + handleTask(task); + } + commReceive = null; + } + catch (TimeoutException e) { + stop = true; + commReceive = null; + } + } while (!stop); + } + catch (TimeoutException e) { + Msg.debug("Failed to send the 'Find Successor' request"); + } + catch (MsgException e) { + Msg.debug("Failed to receive Find Successor"); + } + + return successor; + + } + /** + * @brief This function is called periodically. It checks the immediate + * successor of the current node. + */ + void stabilize() { + Msg.debug("Stabilizing node"); + int candidateId; + int successorId = fingers[0]; + if (successorId != this.id){ + candidateId = remoteGetPredecessor(successorId); + } + else { + candidateId = predId; + } + //This node is a candidate to become my new successor + if (candidateId != -1 && isInInterval(candidateId, this.id + 1, successorId - 1)) { + setFinger(0, candidateId); + } + if (successorId != this.id) { + remoteNotify(successorId, this.id); + } + + } + /** + * \brief Notifies the current node that its predecessor may have changed. + * \param candidate_id the possible new predecessor + */ + void notify(int predecessorCandidateId) { + if (predId == -1 || isInInterval(predecessorCandidateId, predId + 1, this.id - 1 )) { + setPredecessor(predecessorCandidateId); + } + else { + //Don't have to change the predecessor. + } + } + /** + * \brief Notifies a remote node that its predecessor may have changed. + * \param notify_id id of the node to notify + * \param candidate_id the possible new predecessor + */ + void remoteNotify(int notifyId, int predecessorCandidateId) { + Msg.debug("Sending a 'Notify' request to " + notifyId); + Task sentTask = new NotifyTask(host.getName(), this.mailbox, predecessorCandidateId); + sentTask.dsend(Integer.toString(notifyId)); + } + /** + * \brief This function is called periodically. + * It refreshes the finger table of the current node. + */ + void fixFingers() { + Msg.debug("Fixing fingers"); + int i = this.nextFingerToFix; + int id = this.findSuccessor(this.id + (int)Math.pow(2,i)); //FIXME: SLOW + if (id != -1) { + if (id != fingers[i]) { + setFinger(i, id); + } + nextFingerToFix = (i + 1) % Common.NB_BITS; + } + } + /** + * \brief This function is called periodically. + * It checks whether the predecessor has failed + */ + void checkPredecessor() { + //TODO + } + /** + * \brief Performs a find successor request to a random id. + */ + void randomLookup() { + int id = 1337; + //Msg.info("Making a lookup request for id " + id); + findSuccessor(id); + } + + + + /** + * @brief Returns the closest preceding finger of an id + * with respect to the finger table of the current node. + * @param id the id to find + * \return the closest preceding finger of that id + */ + int closestPrecedingNode(int id) { + int i; + for (i = Common.NB_BITS - 1; i >= 0; i--) { + if (isInInterval(fingers[i], this.id + 1, id - 1)) { + return fingers[i]; + } + } + return this.id; + } + /** + * @brief Returns whether an id belongs to the interval [start, end]. + * + * The parameters are noramlized to make sure they are between 0 and nb_keys - 1). + * 1 belongs to [62, 3] + * 1 does not belong to [3, 62] + * 63 belongs to [62, 3] + * 63 does not belong to [3, 62] + * 24 belongs to [21, 29] + * 24 does not belong to [29, 21] + * + * \param id id to check + * \param start lower bound + * \param end upper bound + * \return a non-zero value if id in in [start, end] + */ + static boolean isInInterval(int id, int start, int end) { + id = normalize(id); + start = normalize(start); + end = normalize(end); + + // make sure end >= start and id >= start + if (end < start) { + end += Common.NB_KEYS; + } + if (id < start) { + id += Common.NB_KEYS; + } + return (id <= end); + + } + /** + * @brief Turns an id into an equivalent id in [0, nb_keys). + * @param id an id + * @return the corresponding normalized id + */ + static int normalize(int id) { + return id & (Common.NB_KEYS - 1); + } + /** + * \brief Sets a finger of the current node. + * \param finger_index index of the finger to set (0 to nb_bits - 1) + * \param id the id to set for this finger + */ + void setFinger(int fingerIndex, int id) { + if (id != fingers[fingerIndex]) { + fingers[fingerIndex] = id; + lastChangeDate = Msg.getClock(); + } + } +} diff --git a/examples/chord/NotifyTask.java b/examples/chord/NotifyTask.java new file mode 100644 index 0000000000..d3e8f2e057 --- /dev/null +++ b/examples/chord/NotifyTask.java @@ -0,0 +1,9 @@ +package chord; + +public class NotifyTask extends ChordTask { + public int requestId; + public NotifyTask(String issuerHostname, String answerTo, int requestId) { + super(issuerHostname, answerTo); + this.requestId = requestId; + } +} diff --git a/examples/chord/chord.xml b/examples/chord/chord.xml new file mode 100644 index 0000000000..f04ba2d10f --- /dev/null +++ b/examples/chord/chord.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/chord/chord10.xml b/examples/chord/chord10.xml new file mode 100644 index 0000000000..a2510d2f97 --- /dev/null +++ b/examples/chord/chord10.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/examples/chord/chord100.xml b/examples/chord/chord100.xml new file mode 100644 index 0000000000..f325f92c17 --- /dev/null +++ b/examples/chord/chord100.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/chord/chord1000.xml b/examples/chord/chord1000.xml new file mode 100644 index 0000000000..d0658832a1 --- /dev/null +++ b/examples/chord/chord1000.xml @@ -0,0 +1,1004 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/chord/chord10000.xml b/examples/chord/chord10000.xml new file mode 100644 index 0000000000..e0898b2b68 --- /dev/null +++ b/examples/chord/chord10000.xml @@ -0,0 +1,10004 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/chord/chord90.xml b/examples/chord/chord90.xml new file mode 100644 index 0000000000..495468e442 --- /dev/null +++ b/examples/chord/chord90.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +